Merge pull request #21375 from marination/commonify-warehouse-autofill

chore: Commonify auto-filling warehouses in child tables
diff --git a/erpnext/accounts/deferred_revenue.py b/erpnext/accounts/deferred_revenue.py
index 3b6a588..b0210e5 100644
--- a/erpnext/accounts/deferred_revenue.py
+++ b/erpnext/accounts/deferred_revenue.py
@@ -2,9 +2,10 @@
 
 import frappe
 from frappe import _
-from frappe.utils import date_diff, add_months, today, getdate, add_days, flt, get_last_day
+from frappe.utils import date_diff, add_months, today, getdate, add_days, flt, get_last_day, cint, get_link_to_form
 from erpnext.accounts.utils import get_account_currency
 from frappe.email import sendmail_to_system_managers
+from frappe.utils.background_jobs import enqueue
 
 def validate_service_stop_date(doc):
 	''' Validates service_stop_date for Purchase Invoice and Sales Invoice '''
@@ -32,8 +33,20 @@
 		if old_stop_dates and old_stop_dates.get(item.name) and item.service_stop_date!=old_stop_dates.get(item.name):
 			frappe.throw(_("Cannot change Service Stop Date for item in row {0}").format(item.idx))
 
-def convert_deferred_expense_to_expense(start_date=None, end_date=None):
+def build_conditions(process_type, account, company):
+	conditions=''
+	deferred_account = "item.deferred_revenue_account" if process_type=="Income" else "item.deferred_expense_account"
+
+	if account:
+		conditions += "AND %s='%s'"%(deferred_account, account)
+	elif company:
+		conditions += "AND p.company='%s'"%(company)
+
+	return conditions
+
+def convert_deferred_expense_to_expense(deferred_process, start_date=None, end_date=None, conditions=''):
 	# book the expense/income on the last day, but it will be trigger on the 1st of month at 12:00 AM
+
 	if not start_date:
 		start_date = add_months(today(), -1)
 	if not end_date:
@@ -41,18 +54,25 @@
 
 	# check for the purchase invoice for which GL entries has to be done
 	invoices = frappe.db.sql_list('''
-		select distinct parent from `tabPurchase Invoice Item`
-		where service_start_date<=%s and service_end_date>=%s
-		and enable_deferred_expense = 1 and docstatus = 1 and ifnull(amount, 0) > 0
-	''', (end_date, start_date))
+		select distinct item.parent
+		from `tabPurchase Invoice Item` item, `tabPurchase Invoice` p
+		where item.service_start_date<=%s and item.service_end_date>=%s
+		and item.enable_deferred_expense = 1 and item.parent=p.name
+		and item.docstatus = 1 and ifnull(item.amount, 0) > 0
+		{0}
+	'''.format(conditions), (end_date, start_date)) #nosec
 
 	# For each invoice, book deferred expense
 	for invoice in invoices:
 		doc = frappe.get_doc("Purchase Invoice", invoice)
-		book_deferred_income_or_expense(doc, end_date)
+		book_deferred_income_or_expense(doc, deferred_process, end_date)
 
-def convert_deferred_revenue_to_income(start_date=None, end_date=None):
+	if frappe.flags.deferred_accounting_error:
+		send_mail(deferred_process)
+
+def convert_deferred_revenue_to_income(deferred_process, start_date=None, end_date=None, conditions=''):
 	# book the expense/income on the last day, but it will be trigger on the 1st of month at 12:00 AM
+
 	if not start_date:
 		start_date = add_months(today(), -1)
 	if not end_date:
@@ -60,14 +80,20 @@
 
 	# check for the sales invoice for which GL entries has to be done
 	invoices = frappe.db.sql_list('''
-		select distinct parent from `tabSales Invoice Item`
-		where service_start_date<=%s and service_end_date>=%s
-		and enable_deferred_revenue = 1 and docstatus = 1 and ifnull(amount, 0) > 0
-	''', (end_date, start_date))
+		select distinct item.parent
+		from `tabSales Invoice Item` item, `tabSales Invoice` p
+		where item.service_start_date<=%s and item.service_end_date>=%s
+		and item.enable_deferred_revenue = 1 and item.parent=p.name
+		and item.docstatus = 1 and ifnull(item.amount, 0) > 0
+		{0}
+	'''.format(conditions), (end_date, start_date)) #nosec
 
 	for invoice in invoices:
 		doc = frappe.get_doc("Sales Invoice", invoice)
-		book_deferred_income_or_expense(doc, end_date)
+		book_deferred_income_or_expense(doc, deferred_process, end_date)
+
+	if frappe.flags.deferred_accounting_error:
+		send_mail(deferred_process)
 
 def get_booking_dates(doc, item, posting_date=None):
 	if not posting_date:
@@ -136,7 +162,7 @@
 
 	return amount, base_amount
 
-def book_deferred_income_or_expense(doc, posting_date=None):
+def book_deferred_income_or_expense(doc, deferred_process, posting_date=None):
 	enable_check = "enable_deferred_revenue" \
 		if doc.doctype=="Sales Invoice" else "enable_deferred_expense"
 
@@ -159,7 +185,11 @@
 			total_days, total_booking_days, account_currency)
 
 		make_gl_entries(doc, credit_account, debit_account, against,
-			amount, base_amount, end_date, project, account_currency, item.cost_center, item.name)
+			amount, base_amount, end_date, project, account_currency, item.cost_center, item.name, deferred_process)
+
+		# Returned in case of any errors because it tries to submit the same record again and again in case of errors
+		if frappe.flags.deferred_accounting_error:
+			return
 
 		if getdate(end_date) < getdate(posting_date) and not last_gl_entry:
 			_book_deferred_revenue_or_expense(item)
@@ -169,8 +199,30 @@
 		if item.get(enable_check):
 			_book_deferred_revenue_or_expense(item)
 
+def process_deferred_accounting(posting_date=today()):
+	''' Converts deferred income/expense into income/expense
+		Executed via background jobs on every month end '''
+
+	if not cint(frappe.db.get_singles_value('Accounts Settings', 'automatically_process_deferred_accounting_entry')):
+		return
+
+	start_date = add_months(today(), -1)
+	end_date = add_days(today(), -1)
+
+	for record_type in ('Income', 'Expense'):
+		doc = frappe.get_doc(dict(
+			doctype='Process Deferred Accounting',
+			posting_date=posting_date,
+			start_date=start_date,
+			end_date=end_date,
+			type=record_type
+		))
+
+		doc.insert()
+		doc.submit()
+
 def make_gl_entries(doc, credit_account, debit_account, against,
-	amount, base_amount, posting_date, project, account_currency, cost_center, voucher_detail_no):
+	amount, base_amount, posting_date, project, account_currency, cost_center, voucher_detail_no, deferred_process=None):
 	# GL Entry for crediting the amount in the deferred expense
 	from erpnext.accounts.general_ledger import make_gl_entries
 
@@ -186,7 +238,9 @@
 			"cost_center": cost_center,
 			"voucher_detail_no": voucher_detail_no,
 			'posting_date': posting_date,
-			'project': project
+			'project': project,
+			'against_voucher_type': 'Process Deferred Accounting',
+			'against_voucher': deferred_process
 		}, account_currency)
 	)
 	# GL Entry to debit the amount from the expense
@@ -199,7 +253,9 @@
 			"cost_center": cost_center,
 			"voucher_detail_no": voucher_detail_no,
 			'posting_date': posting_date,
-			'project': project
+			'project': project,
+			'against_voucher_type': 'Process Deferred Accounting',
+			'against_voucher': deferred_process
 		}, account_currency)
 	)
 
@@ -209,7 +265,16 @@
 			frappe.db.commit()
 		except:
 			frappe.db.rollback()
-			title = _("Error while processing deferred accounting for {0}").format(doc.name)
 			traceback = frappe.get_traceback()
-			frappe.log_error(message=traceback , title=title)
-			sendmail_to_system_managers(title, traceback)
\ No newline at end of file
+			frappe.log_error(message=traceback)
+
+			frappe.flags.deferred_accounting_error = True
+
+def send_mail(deferred_process):
+	title = _("Error while processing deferred accounting for {0}".format(deferred_process))
+	content = _("""
+		Deferred accounting failed for some invoices:
+		Please check Process Deferred Accounting {0}
+		and submit manually after resolving errors
+	""").format(get_link_to_form('Process Deferred Accounting', deferred_process))
+	sendmail_to_system_managers(title, content)
diff --git a/erpnext/accounts/desk_page/accounting/accounting.json b/erpnext/accounts/desk_page/accounting/accounting.json
index 8566ead..0d6aca6 100644
--- a/erpnext/accounts/desk_page/accounting/accounting.json
+++ b/erpnext/accounts/desk_page/accounting/accounting.json
@@ -8,7 +8,7 @@
   {
    "hidden": 0,
    "label": "General Ledger",
-   "links": "[\n    {\n        \"description\": \"Accounting journal entries.\",\n        \"label\": \"Journal Entry\",\n        \"name\": \"Journal Entry\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"dependencies\": [\n            \"GL Entry\"\n        ],\n        \"doctype\": \"GL Entry\",\n        \"is_query_report\": true,\n        \"label\": \"General Ledger\",\n        \"name\": \"General Ledger\",\n        \"type\": \"report\"\n    },\n    {\n        \"dependencies\": [\n            \"Sales Invoice\"\n        ],\n        \"doctype\": \"Sales Invoice\",\n        \"is_query_report\": true,\n        \"label\": \"Customer Ledger Summary\",\n        \"name\": \"Customer Ledger Summary\",\n        \"type\": \"report\"\n    },\n    {\n        \"dependencies\": [\n            \"Sales Invoice\"\n        ],\n        \"doctype\": \"Sales Invoice\",\n        \"is_query_report\": true,\n        \"label\": \"Supplier Ledger Summary\",\n        \"name\": \"Supplier Ledger Summary\",\n        \"type\": \"report\"\n    }\n]"
+   "links": "[\n    {\n        \"description\": \"Accounting journal entries.\",\n        \"label\": \"Journal Entry\",\n        \"name\": \"Journal Entry\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"description\": \"Make journal entries from a template.\",\n        \"label\": \"Journal Entry Template\",\n        \"name\": \"Journal Entry Template\",\n        \"type\": \"doctype\"\n    },\n    \n    {\n        \"dependencies\": [\n            \"GL Entry\"\n        ],\n        \"doctype\": \"GL Entry\",\n        \"is_query_report\": true,\n        \"label\": \"General Ledger\",\n        \"name\": \"General Ledger\",\n        \"type\": \"report\"\n    },\n    {\n        \"dependencies\": [\n            \"Sales Invoice\"\n        ],\n        \"doctype\": \"Sales Invoice\",\n        \"is_query_report\": true,\n        \"label\": \"Customer Ledger Summary\",\n        \"name\": \"Customer Ledger Summary\",\n        \"type\": \"report\"\n    },\n    {\n        \"dependencies\": [\n            \"Sales Invoice\"\n        ],\n        \"doctype\": \"Sales Invoice\",\n        \"is_query_report\": true,\n        \"label\": \"Supplier Ledger Summary\",\n        \"name\": \"Supplier Ledger Summary\",\n        \"type\": \"report\"\n    }\n]"
   },
   {
    "hidden": 0,
@@ -47,8 +47,8 @@
   },
   {
    "hidden": 0,
-   "label": "Banking and Payments",
-   "links": "[\n    {\n        \"description\": \"Match non-linked Invoices and Payments.\",\n        \"label\": \"Match Payments with Invoices\",\n        \"name\": \"Payment Reconciliation\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"description\": \"Update bank payment dates with journals.\",\n        \"label\": \"Update Bank Transaction Dates\",\n        \"name\": \"Bank Reconciliation\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"Invoice Discounting\",\n        \"name\": \"Invoice Discounting\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"dependencies\": [\n            \"Journal Entry\"\n        ],\n        \"doctype\": \"Journal Entry\",\n        \"is_query_report\": true,\n        \"label\": \"Bank Reconciliation Statement\",\n        \"name\": \"Bank Reconciliation Statement\",\n        \"type\": \"report\"\n    },\n    {\n        \"icon\": \"fa fa-bar-chart\",\n        \"label\": \"Bank Reconciliation\",\n        \"name\": \"bank-reconciliation\",\n        \"type\": \"page\"\n    },\n    {\n        \"dependencies\": [\n            \"Journal Entry\"\n        ],\n        \"doctype\": \"Journal Entry\",\n        \"is_query_report\": true,\n        \"label\": \"Bank Clearance Summary\",\n        \"name\": \"Bank Clearance Summary\",\n        \"type\": \"report\"\n    },\n    {\n        \"label\": \"Bank Guarantee\",\n        \"name\": \"Bank Guarantee\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"description\": \"Setup cheque dimensions for printing\",\n        \"label\": \"Cheque Print Template\",\n        \"name\": \"Cheque Print Template\",\n        \"type\": \"doctype\"\n    }\n]"
+   "links": "[\n    {\n        \"description\": \"Match non-linked Invoices and Payments.\",\n        \"label\": \"Match Payments with Invoices\",\n        \"name\": \"Payment Reconciliation\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"description\": \"Update bank payment dates with journals.\",\n        \"label\": \"Update Bank Clearance Dates\",\n        \"name\": \"Bank Clearance\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"Invoice Discounting\",\n        \"name\": \"Invoice Discounting\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"dependencies\": [\n            \"Journal Entry\"\n        ],\n        \"doctype\": \"Journal Entry\",\n        \"is_query_report\": true,\n        \"label\": \"Bank Reconciliation Statement\",\n        \"name\": \"Bank Reconciliation Statement\",\n        \"type\": \"report\"\n    },\n    {\n        \"icon\": \"fa fa-bar-chart\",\n        \"label\": \"Bank Reconciliation\",\n        \"name\": \"bank-reconciliation\",\n        \"type\": \"page\"\n    },\n    {\n        \"dependencies\": [\n            \"Journal Entry\"\n        ],\n        \"doctype\": \"Journal Entry\",\n        \"is_query_report\": true,\n        \"label\": \"Bank Clearance Summary\",\n        \"name\": \"Bank Clearance Summary\",\n        \"type\": \"report\"\n    },\n    {\n        \"label\": \"Bank Guarantee\",\n        \"name\": \"Bank Guarantee\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"description\": \"Setup cheque dimensions for printing\",\n        \"label\": \"Cheque Print Template\",\n        \"name\": \"Cheque Print Template\",\n        \"type\": \"doctype\"\n    }\n]",
+   "title": "Banking and Payments"
   },
   {
    "hidden": 0,
@@ -103,7 +103,7 @@
  "idx": 0,
  "is_standard": 1,
  "label": "Accounting",
- "modified": "2020-04-01 11:28:50.925719",
+ "modified": "2020-04-29 12:17:34.844397",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "Accounting",
diff --git a/erpnext/accounts/doctype/account_subtype/account_subtype.json b/erpnext/accounts/doctype/account_subtype/account_subtype.json
deleted file mode 100644
index 6b1f2a2..0000000
--- a/erpnext/accounts/doctype/account_subtype/account_subtype.json
+++ /dev/null
@@ -1,134 +0,0 @@
-{
- "allow_copy": 0, 
- "allow_events_in_timeline": 0, 
- "allow_guest_to_view": 0, 
- "allow_import": 1, 
- "allow_rename": 1, 
- "autoname": "field:account_subtype", 
- "beta": 0, 
- "creation": "2018-10-25 15:46:08.054586", 
- "custom": 0, 
- "docstatus": 0, 
- "doctype": "DocType", 
- "document_type": "", 
- "editable_grid": 1, 
- "engine": "InnoDB", 
- "fields": [
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "account_subtype", 
-   "fieldtype": "Data", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Account Subtype", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 1
-  }
- ], 
- "has_web_view": 0, 
- "hide_heading": 0, 
- "hide_toolbar": 0, 
- "idx": 0, 
- "image_view": 0, 
- "in_create": 0, 
- "is_submittable": 0, 
- "issingle": 0, 
- "istable": 0, 
- "max_attachments": 0, 
- "modified": "2018-10-25 15:47:03.841390", 
- "modified_by": "Administrator", 
- "module": "Accounts", 
- "name": "Account Subtype", 
- "name_case": "", 
- "owner": "Administrator", 
- "permissions": [
-  {
-   "amend": 0, 
-   "cancel": 0, 
-   "create": 1, 
-   "delete": 1, 
-   "email": 1, 
-   "export": 1, 
-   "if_owner": 0, 
-   "import": 0, 
-   "permlevel": 0, 
-   "print": 1, 
-   "read": 1, 
-   "report": 1, 
-   "role": "System Manager", 
-   "set_user_permissions": 0, 
-   "share": 1, 
-   "submit": 0, 
-   "write": 1
-  }, 
-  {
-   "amend": 0, 
-   "cancel": 0, 
-   "create": 1, 
-   "delete": 1, 
-   "email": 1, 
-   "export": 1, 
-   "if_owner": 0, 
-   "import": 0, 
-   "permlevel": 0, 
-   "print": 1, 
-   "read": 1, 
-   "report": 1, 
-   "role": "Accounts Manager", 
-   "set_user_permissions": 0, 
-   "share": 1, 
-   "submit": 0, 
-   "write": 1
-  }, 
-  {
-   "amend": 0, 
-   "cancel": 0, 
-   "create": 1, 
-   "delete": 1, 
-   "email": 1, 
-   "export": 1, 
-   "if_owner": 0, 
-   "import": 0, 
-   "permlevel": 0, 
-   "print": 1, 
-   "read": 1, 
-   "report": 1, 
-   "role": "Accounts User", 
-   "set_user_permissions": 0, 
-   "share": 1, 
-   "submit": 0, 
-   "write": 1
-  }
- ], 
- "quick_entry": 1, 
- "read_only": 0, 
- "read_only_onload": 0, 
- "show_name_in_global_search": 0, 
- "sort_field": "modified", 
- "sort_order": "DESC", 
- "track_changes": 0, 
- "track_seen": 0, 
- "track_views": 0
-}
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/account_subtype/test_account_subtype.py b/erpnext/accounts/doctype/account_subtype/test_account_subtype.py
deleted file mode 100644
index c37b5b9..0000000
--- a/erpnext/accounts/doctype/account_subtype/test_account_subtype.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# -*- coding: utf-8 -*-
-# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
-# See license.txt
-from __future__ import unicode_literals
-
-import unittest
-
-class TestAccountSubtype(unittest.TestCase):
-	pass
diff --git a/erpnext/accounts/doctype/account_type/account_type.js b/erpnext/accounts/doctype/account_type/account_type.js
deleted file mode 100644
index 858b56c..0000000
--- a/erpnext/accounts/doctype/account_type/account_type.js
+++ /dev/null
@@ -1,8 +0,0 @@
-// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
-// For license information, please see license.txt
-
-frappe.ui.form.on('Account Type', {
-	refresh: function() {
-
-	}
-});
diff --git a/erpnext/accounts/doctype/account_type/account_type.json b/erpnext/accounts/doctype/account_type/account_type.json
deleted file mode 100644
index 6b8f724..0000000
--- a/erpnext/accounts/doctype/account_type/account_type.json
+++ /dev/null
@@ -1,134 +0,0 @@
-{
- "allow_copy": 0, 
- "allow_events_in_timeline": 0, 
- "allow_guest_to_view": 0, 
- "allow_import": 1, 
- "allow_rename": 1, 
- "autoname": "field:account_type", 
- "beta": 0, 
- "creation": "2018-10-25 15:45:45.789963", 
- "custom": 0, 
- "docstatus": 0, 
- "doctype": "DocType", 
- "document_type": "", 
- "editable_grid": 1, 
- "engine": "InnoDB", 
- "fields": [
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "account_type", 
-   "fieldtype": "Data", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Account Type", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 1
-  }
- ], 
- "has_web_view": 0, 
- "hide_heading": 0, 
- "hide_toolbar": 0, 
- "idx": 0, 
- "image_view": 0, 
- "in_create": 0, 
- "is_submittable": 0, 
- "issingle": 0, 
- "istable": 0, 
- "max_attachments": 0, 
- "modified": "2018-10-25 15:46:51.042604", 
- "modified_by": "Administrator", 
- "module": "Accounts", 
- "name": "Account Type", 
- "name_case": "", 
- "owner": "Administrator", 
- "permissions": [
-  {
-   "amend": 0, 
-   "cancel": 0, 
-   "create": 1, 
-   "delete": 1, 
-   "email": 1, 
-   "export": 1, 
-   "if_owner": 0, 
-   "import": 0, 
-   "permlevel": 0, 
-   "print": 1, 
-   "read": 1, 
-   "report": 1, 
-   "role": "System Manager", 
-   "set_user_permissions": 0, 
-   "share": 1, 
-   "submit": 0, 
-   "write": 1
-  }, 
-  {
-   "amend": 0, 
-   "cancel": 0, 
-   "create": 1, 
-   "delete": 1, 
-   "email": 1, 
-   "export": 1, 
-   "if_owner": 0, 
-   "import": 0, 
-   "permlevel": 0, 
-   "print": 1, 
-   "read": 1, 
-   "report": 1, 
-   "role": "Accounts Manager", 
-   "set_user_permissions": 0, 
-   "share": 1, 
-   "submit": 0, 
-   "write": 1
-  }, 
-  {
-   "amend": 0, 
-   "cancel": 0, 
-   "create": 1, 
-   "delete": 1, 
-   "email": 1, 
-   "export": 1, 
-   "if_owner": 0, 
-   "import": 0, 
-   "permlevel": 0, 
-   "print": 1, 
-   "read": 1, 
-   "report": 1, 
-   "role": "Accounts User", 
-   "set_user_permissions": 0, 
-   "share": 1, 
-   "submit": 0, 
-   "write": 1
-  }
- ], 
- "quick_entry": 1, 
- "read_only": 0, 
- "read_only_onload": 0, 
- "show_name_in_global_search": 0, 
- "sort_field": "modified", 
- "sort_order": "DESC", 
- "track_changes": 0, 
- "track_seen": 0, 
- "track_views": 0
-}
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/account_type/test_account_type.js b/erpnext/accounts/doctype/account_type/test_account_type.js
deleted file mode 100644
index 76e434f..0000000
--- a/erpnext/accounts/doctype/account_type/test_account_type.js
+++ /dev/null
@@ -1,23 +0,0 @@
-/* eslint-disable */
-// rename this file from _test_[name] to test_[name] to activate
-// and remove above this line
-
-QUnit.test("test: Account Type", function (assert) {
-	let done = assert.async();
-
-	// number of asserts
-	assert.expect(1);
-
-	frappe.run_serially([
-		// insert a new Account Type
-		() => frappe.tests.make('Account Type', [
-			// values to be set
-			{key: 'value'}
-		]),
-		() => {
-			assert.equal(cur_frm.doc.key, 'value');
-		},
-		() => done()
-	]);
-
-});
diff --git a/erpnext/accounts/doctype/account_type/test_account_type.py b/erpnext/accounts/doctype/account_type/test_account_type.py
deleted file mode 100644
index 824c2f6..0000000
--- a/erpnext/accounts/doctype/account_type/test_account_type.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# -*- coding: utf-8 -*-
-# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
-# See license.txt
-from __future__ import unicode_literals
-
-import unittest
-
-class TestAccountType(unittest.TestCase):
-	pass
diff --git a/erpnext/accounts/doctype/accounting_period/accounting_period.py b/erpnext/accounts/doctype/accounting_period/accounting_period.py
index f48d6df..df6cedd 100644
--- a/erpnext/accounts/doctype/accounting_period/accounting_period.py
+++ b/erpnext/accounts/doctype/accounting_period/accounting_period.py
@@ -42,7 +42,7 @@
 	def get_doctypes_for_closing(self):
 		docs_for_closing = []
 		doctypes = ["Sales Invoice", "Purchase Invoice", "Journal Entry", "Payroll Entry", \
-			"Bank Reconciliation", "Asset", "Stock Entry"]
+			"Bank Clearance", "Asset", "Stock Entry"]
 		closed_doctypes = [{"document_type": doctype, "closed": 1} for doctype in doctypes]
 		for closed_doctype in closed_doctypes:
 			docs_for_closing.append(closed_doctype)
diff --git a/erpnext/accounts/doctype/accounts_settings/accounts_settings.json b/erpnext/accounts/doctype/accounts_settings/accounts_settings.json
index 4ff4212..353ff77 100644
--- a/erpnext/accounts/doctype/accounts_settings/accounts_settings.json
+++ b/erpnext/accounts/doctype/accounts_settings/accounts_settings.json
@@ -1,210 +1,226 @@
 {
-   "creation": "2013-06-24 15:49:57",
-   "description": "Settings for Accounts",
-   "doctype": "DocType",
-   "document_type": "Other",
-   "editable_grid": 1,
-   "engine": "InnoDB",
-   "field_order": [
-    "auto_accounting_for_stock",
-    "acc_frozen_upto",
-    "frozen_accounts_modifier",
-    "determine_address_tax_category_from",
-    "over_billing_allowance",
-    "column_break_4",
-    "credit_controller",
-    "check_supplier_invoice_uniqueness",
-    "make_payment_via_journal_entry",
-    "unlink_payment_on_cancellation_of_invoice",
-    "unlink_advance_payment_on_cancelation_of_order",
-    "book_asset_depreciation_entry_automatically",
-    "allow_cost_center_in_entry_of_bs_account",
-    "add_taxes_from_item_tax_template",
-    "automatically_fetch_payment_terms",
-    "print_settings",
-    "show_inclusive_tax_in_print",
-    "column_break_12",
-    "show_payment_schedule_in_print",
-    "currency_exchange_section",
-    "allow_stale",
-    "stale_days",
-    "report_settings_sb",
-    "use_custom_cash_flow"
-   ],
-   "fields": [
-    {
-     "default": "1",
-     "description": "If enabled, the system will post accounting entries for inventory automatically.",
-     "fieldname": "auto_accounting_for_stock",
-     "fieldtype": "Check",
-     "hidden": 1,
-     "in_list_view": 1,
-     "label": "Make Accounting Entry For Every Stock Movement"
-    },
-    {
-     "description": "Accounting entry frozen up to this date, nobody can do / modify entry except role specified below.",
-     "fieldname": "acc_frozen_upto",
-     "fieldtype": "Date",
-     "in_list_view": 1,
-     "label": "Accounts Frozen Upto"
-    },
-    {
-     "description": "Users with this role are allowed to set frozen accounts and create / modify accounting entries against frozen accounts",
-     "fieldname": "frozen_accounts_modifier",
-     "fieldtype": "Link",
-     "in_list_view": 1,
-     "label": "Role Allowed to Set Frozen Accounts & Edit Frozen Entries",
-     "options": "Role"
-    },
-    {
-     "default": "Billing Address",
-     "description": "Address used to determine Tax Category in transactions.",
-     "fieldname": "determine_address_tax_category_from",
-     "fieldtype": "Select",
-     "label": "Determine Address Tax Category From",
-     "options": "Billing Address\nShipping Address"
-    },
-    {
-     "fieldname": "column_break_4",
-     "fieldtype": "Column Break"
-    },
-    {
-     "description": "Role that is allowed to submit transactions that exceed credit limits set.",
-     "fieldname": "credit_controller",
-     "fieldtype": "Link",
-     "in_list_view": 1,
-     "label": "Credit Controller",
-     "options": "Role"
-    },
-    {
-     "fieldname": "check_supplier_invoice_uniqueness",
-     "fieldtype": "Check",
-     "label": "Check Supplier Invoice Number Uniqueness"
-    },
-    {
-     "fieldname": "make_payment_via_journal_entry",
-     "fieldtype": "Check",
-     "label": "Make Payment via Journal Entry"
-    },
-    {
-     "default": "1",
-     "fieldname": "unlink_payment_on_cancellation_of_invoice",
-     "fieldtype": "Check",
-     "label": "Unlink Payment on Cancellation of Invoice"
-    },
-    {
-     "default": "1",
-     "fieldname": "unlink_advance_payment_on_cancelation_of_order",
-     "fieldtype": "Check",
-     "label": "Unlink Advance Payment on Cancelation of Order"
-    },
-    {
-     "default": "1",
-     "fieldname": "book_asset_depreciation_entry_automatically",
-     "fieldtype": "Check",
-     "label": "Book Asset Depreciation Entry Automatically"
-    },
-    {
-     "fieldname": "allow_cost_center_in_entry_of_bs_account",
-     "fieldtype": "Check",
-     "label": "Allow Cost Center In Entry of Balance Sheet Account"
-    },
-    {
-     "default": "1",
-     "fieldname": "add_taxes_from_item_tax_template",
-     "fieldtype": "Check",
-     "label": "Automatically Add Taxes and Charges from Item Tax Template"
-    },
-    {
-     "fieldname": "print_settings",
-     "fieldtype": "Section Break",
-     "label": "Print Settings"
-    },
-    {
-     "fieldname": "show_inclusive_tax_in_print",
-     "fieldtype": "Check",
-     "label": "Show Inclusive Tax In Print"
-    },
-    {
-     "fieldname": "column_break_12",
-     "fieldtype": "Column Break"
-    },
-    {
-     "fieldname": "show_payment_schedule_in_print",
-     "fieldtype": "Check",
-     "label": "Show Payment Schedule in Print"
-    },
-    {
-     "fieldname": "currency_exchange_section",
-     "fieldtype": "Section Break",
-     "label": "Currency Exchange Settings"
-    },
-    {
-     "default": "1",
-     "fieldname": "allow_stale",
-     "fieldtype": "Check",
-     "in_list_view": 1,
-     "label": "Allow Stale Exchange Rates"
-    },
-    {
-     "default": "1",
-     "depends_on": "eval:doc.allow_stale==0",
-     "fieldname": "stale_days",
-     "fieldtype": "Int",
-     "label": "Stale Days"
-    },
-    {
-     "fieldname": "report_settings_sb",
-     "fieldtype": "Section Break",
-     "label": "Report Settings"
-    },
-    {
-     "default": "0",
-     "description": "Only select if you have setup Cash Flow Mapper documents",
-     "fieldname": "use_custom_cash_flow",
-     "fieldtype": "Check",
-     "label": "Use Custom Cash Flow Format"
-    },
-    {
-     "fieldname": "automatically_fetch_payment_terms",
-     "fieldtype": "Check",
-     "label": "Automatically Fetch Payment Terms"
-    },
-    {
-     "description": "Percentage you are allowed to bill more against the amount ordered. For example: If the order value is $100 for an item and tolerance is set as 10% then you are allowed to bill for $110.",
-     "fieldname": "over_billing_allowance",
-     "fieldtype": "Currency",
-     "label": "Over Billing Allowance (%)"
-    }
-   ],
-   "icon": "icon-cog",
-   "idx": 1,
-   "issingle": 1,
-   "modified": "2019-07-04 18:20:55.789946",
-   "modified_by": "Administrator",
-   "module": "Accounts",
-   "name": "Accounts Settings",
-   "owner": "Administrator",
-   "permissions": [
-    {
-     "create": 1,
-     "email": 1,
-     "print": 1,
-     "read": 1,
-     "role": "Accounts Manager",
-     "share": 1,
-     "write": 1
-    },
-    {
-     "read": 1,
-     "role": "Sales User"
-    },
-    {
-     "read": 1,
-     "role": "Purchase User"
-    }
-   ],
-   "quick_entry": 1,
-   "sort_order": "ASC",
-   "track_changes": 1
+ "actions": [],
+ "creation": "2013-06-24 15:49:57",
+ "description": "Settings for Accounts",
+ "doctype": "DocType",
+ "document_type": "Other",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "auto_accounting_for_stock",
+  "acc_frozen_upto",
+  "frozen_accounts_modifier",
+  "determine_address_tax_category_from",
+  "over_billing_allowance",
+  "column_break_4",
+  "credit_controller",
+  "check_supplier_invoice_uniqueness",
+  "make_payment_via_journal_entry",
+  "unlink_payment_on_cancellation_of_invoice",
+  "unlink_advance_payment_on_cancelation_of_order",
+  "book_asset_depreciation_entry_automatically",
+  "allow_cost_center_in_entry_of_bs_account",
+  "add_taxes_from_item_tax_template",
+  "automatically_fetch_payment_terms",
+  "automatically_process_deferred_accounting_entry",
+  "print_settings",
+  "show_inclusive_tax_in_print",
+  "column_break_12",
+  "show_payment_schedule_in_print",
+  "currency_exchange_section",
+  "allow_stale",
+  "stale_days",
+  "report_settings_sb",
+  "use_custom_cash_flow"
+ ],
+ "fields": [
+  {
+   "default": "1",
+   "description": "If enabled, the system will post accounting entries for inventory automatically.",
+   "fieldname": "auto_accounting_for_stock",
+   "fieldtype": "Check",
+   "hidden": 1,
+   "in_list_view": 1,
+   "label": "Make Accounting Entry For Every Stock Movement"
+  },
+  {
+   "description": "Accounting entry frozen up to this date, nobody can do / modify entry except role specified below.",
+   "fieldname": "acc_frozen_upto",
+   "fieldtype": "Date",
+   "in_list_view": 1,
+   "label": "Accounts Frozen Upto"
+  },
+  {
+   "description": "Users with this role are allowed to set frozen accounts and create / modify accounting entries against frozen accounts",
+   "fieldname": "frozen_accounts_modifier",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "label": "Role Allowed to Set Frozen Accounts & Edit Frozen Entries",
+   "options": "Role"
+  },
+  {
+   "default": "Billing Address",
+   "description": "Address used to determine Tax Category in transactions.",
+   "fieldname": "determine_address_tax_category_from",
+   "fieldtype": "Select",
+   "label": "Determine Address Tax Category From",
+   "options": "Billing Address\nShipping Address"
+  },
+  {
+   "fieldname": "column_break_4",
+   "fieldtype": "Column Break"
+  },
+  {
+   "description": "Role that is allowed to submit transactions that exceed credit limits set.",
+   "fieldname": "credit_controller",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "label": "Credit Controller",
+   "options": "Role"
+  },
+  {
+   "default": "0",
+   "fieldname": "check_supplier_invoice_uniqueness",
+   "fieldtype": "Check",
+   "label": "Check Supplier Invoice Number Uniqueness"
+  },
+  {
+   "default": "0",
+   "fieldname": "make_payment_via_journal_entry",
+   "fieldtype": "Check",
+   "label": "Make Payment via Journal Entry"
+  },
+  {
+   "default": "1",
+   "fieldname": "unlink_payment_on_cancellation_of_invoice",
+   "fieldtype": "Check",
+   "label": "Unlink Payment on Cancellation of Invoice"
+  },
+  {
+   "default": "1",
+   "fieldname": "unlink_advance_payment_on_cancelation_of_order",
+   "fieldtype": "Check",
+   "label": "Unlink Advance Payment on Cancelation of Order"
+  },
+  {
+   "default": "1",
+   "fieldname": "book_asset_depreciation_entry_automatically",
+   "fieldtype": "Check",
+   "label": "Book Asset Depreciation Entry Automatically"
+  },
+  {
+   "default": "0",
+   "fieldname": "allow_cost_center_in_entry_of_bs_account",
+   "fieldtype": "Check",
+   "label": "Allow Cost Center In Entry of Balance Sheet Account"
+  },
+  {
+   "default": "1",
+   "fieldname": "add_taxes_from_item_tax_template",
+   "fieldtype": "Check",
+   "label": "Automatically Add Taxes and Charges from Item Tax Template"
+  },
+  {
+   "fieldname": "print_settings",
+   "fieldtype": "Section Break",
+   "label": "Print Settings"
+  },
+  {
+   "default": "0",
+   "fieldname": "show_inclusive_tax_in_print",
+   "fieldtype": "Check",
+   "label": "Show Inclusive Tax In Print"
+  },
+  {
+   "fieldname": "column_break_12",
+   "fieldtype": "Column Break"
+  },
+  {
+   "default": "0",
+   "fieldname": "show_payment_schedule_in_print",
+   "fieldtype": "Check",
+   "label": "Show Payment Schedule in Print"
+  },
+  {
+   "fieldname": "currency_exchange_section",
+   "fieldtype": "Section Break",
+   "label": "Currency Exchange Settings"
+  },
+  {
+   "default": "1",
+   "fieldname": "allow_stale",
+   "fieldtype": "Check",
+   "in_list_view": 1,
+   "label": "Allow Stale Exchange Rates"
+  },
+  {
+   "default": "1",
+   "depends_on": "eval:doc.allow_stale==0",
+   "fieldname": "stale_days",
+   "fieldtype": "Int",
+   "label": "Stale Days"
+  },
+  {
+   "fieldname": "report_settings_sb",
+   "fieldtype": "Section Break",
+   "label": "Report Settings"
+  },
+  {
+   "default": "0",
+   "description": "Only select if you have setup Cash Flow Mapper documents",
+   "fieldname": "use_custom_cash_flow",
+   "fieldtype": "Check",
+   "label": "Use Custom Cash Flow Format"
+  },
+  {
+   "default": "0",
+   "fieldname": "automatically_fetch_payment_terms",
+   "fieldtype": "Check",
+   "label": "Automatically Fetch Payment Terms"
+  },
+  {
+   "description": "Percentage you are allowed to bill more against the amount ordered. For example: If the order value is $100 for an item and tolerance is set as 10% then you are allowed to bill for $110.",
+   "fieldname": "over_billing_allowance",
+   "fieldtype": "Currency",
+   "label": "Over Billing Allowance (%)"
+  },
+  {
+   "default": "1",
+   "fieldname": "automatically_process_deferred_accounting_entry",
+   "fieldtype": "Check",
+   "label": "Automatically Process Deferred Accounting Entry"
   }
+ ],
+ "icon": "icon-cog",
+ "idx": 1,
+ "issingle": 1,
+ "links": [],
+ "modified": "2019-12-19 16:58:17.395595",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "Accounts Settings",
+ "owner": "Administrator",
+ "permissions": [
+  {
+   "create": 1,
+   "email": 1,
+   "print": 1,
+   "read": 1,
+   "role": "Accounts Manager",
+   "share": 1,
+   "write": 1
+  },
+  {
+   "read": 1,
+   "role": "Sales User"
+  },
+  {
+   "read": 1,
+   "role": "Purchase User"
+  }
+ ],
+ "quick_entry": 1,
+ "sort_field": "modified",
+ "sort_order": "ASC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/allowed_to_transact_with/allowed_to_transact_with.json b/erpnext/accounts/doctype/allowed_to_transact_with/allowed_to_transact_with.json
index f85bc52..e3f2d59 100644
--- a/erpnext/accounts/doctype/allowed_to_transact_with/allowed_to_transact_with.json
+++ b/erpnext/accounts/doctype/allowed_to_transact_with/allowed_to_transact_with.json
@@ -1,74 +1,32 @@
 {
- "allow_copy": 0, 
- "allow_guest_to_view": 0, 
- "allow_import": 0, 
- "allow_rename": 0, 
- "beta": 0, 
- "creation": "2018-04-16 21:50:05.860195", 
- "custom": 0, 
- "docstatus": 0, 
- "doctype": "DocType", 
- "document_type": "", 
- "editable_grid": 1, 
- "engine": "InnoDB", 
+ "actions": [],
+ "creation": "2018-04-16 21:50:05.860195",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "company"
+ ],
  "fields": [
   {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "default": "", 
-   "fieldname": "company", 
-   "fieldtype": "Link", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Company", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Company", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 1, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
+   "fieldname": "company",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "label": "Company",
+   "options": "Company",
+   "reqd": 1
   }
- ], 
- "has_web_view": 0, 
- "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": "2018-04-20 14:00:46.014502", 
- "modified_by": "Administrator", 
- "module": "Accounts", 
- "name": "Allowed To Transact With", 
- "name_case": "", 
- "owner": "Administrator", 
- "permissions": [], 
- "quick_entry": 1, 
- "read_only": 0, 
- "read_only_onload": 0, 
- "show_name_in_global_search": 0, 
- "sort_field": "modified", 
- "sort_order": "DESC", 
- "track_changes": 1, 
- "track_seen": 0
+ ],
+ "istable": 1,
+ "links": [],
+ "modified": "2020-05-01 12:32:34.044911",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "Allowed To Transact With",
+ "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/accounts/doctype/bank_account/bank_account.json b/erpnext/accounts/doctype/bank_account/bank_account.json
index aa9c434..65a0a51 100644
--- a/erpnext/accounts/doctype/bank_account/bank_account.json
+++ b/erpnext/accounts/doctype/bank_account/bank_account.json
@@ -64,13 +64,13 @@
    "fieldname": "account_type",
    "fieldtype": "Link",
    "label": "Account Type",
-   "options": "Account Type"
+   "options": "Bank Account Type"
   },
   {
    "fieldname": "account_subtype",
    "fieldtype": "Link",
    "label": "Account Subtype",
-   "options": "Account Subtype"
+   "options": "Bank Account Subtype"
   },
   {
    "fieldname": "column_break_7",
@@ -200,7 +200,7 @@
   }
  ],
  "links": [],
- "modified": "2020-01-30 20:42:26.458316",
+ "modified": "2020-04-06 21:00:45.379804",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "Bank Account",
diff --git a/erpnext/accounts/doctype/account_subtype/__init__.py b/erpnext/accounts/doctype/bank_account_subtype/__init__.py
similarity index 100%
rename from erpnext/accounts/doctype/account_subtype/__init__.py
rename to erpnext/accounts/doctype/bank_account_subtype/__init__.py
diff --git a/erpnext/accounts/doctype/account_subtype/account_subtype.js b/erpnext/accounts/doctype/bank_account_subtype/bank_account_subtype.js
similarity index 77%
rename from erpnext/accounts/doctype/account_subtype/account_subtype.js
rename to erpnext/accounts/doctype/bank_account_subtype/bank_account_subtype.js
index 30144ad..f045665 100644
--- a/erpnext/accounts/doctype/account_subtype/account_subtype.js
+++ b/erpnext/accounts/doctype/bank_account_subtype/bank_account_subtype.js
@@ -1,7 +1,7 @@
 // Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
 // For license information, please see license.txt
 
-frappe.ui.form.on('Account Subtype', {
+frappe.ui.form.on('Bank Account Subtype', {
 	refresh: function() {
 
 	}
diff --git a/erpnext/accounts/doctype/bank_account_subtype/bank_account_subtype.json b/erpnext/accounts/doctype/bank_account_subtype/bank_account_subtype.json
new file mode 100644
index 0000000..f875db8
--- /dev/null
+++ b/erpnext/accounts/doctype/bank_account_subtype/bank_account_subtype.json
@@ -0,0 +1,134 @@
+{
+ "allow_copy": 0,
+ "allow_events_in_timeline": 0,
+ "allow_guest_to_view": 0,
+ "allow_import": 1,
+ "allow_rename": 1,
+ "autoname": "field:account_subtype",
+ "beta": 0,
+ "creation": "2018-10-25 15:46:08.054586",
+ "custom": 0,
+ "docstatus": 0,
+ "doctype": "DocType",
+ "document_type": "",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "fields": [
+  {
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fieldname": "account_subtype",
+   "fieldtype": "Data",
+   "hidden": 0,
+   "ignore_user_permissions": 0,
+   "ignore_xss_filter": 0,
+   "in_filter": 0,
+   "in_global_search": 0,
+   "in_list_view": 0,
+   "in_standard_filter": 0,
+   "label": "Account Subtype",
+   "length": 0,
+   "no_copy": 0,
+   "permlevel": 0,
+   "precision": "",
+   "print_hide": 0,
+   "print_hide_if_no_value": 0,
+   "read_only": 0,
+   "remember_last_selected_value": 0,
+   "report_hide": 0,
+   "reqd": 0,
+   "search_index": 0,
+   "set_only_once": 0,
+   "translatable": 0,
+   "unique": 1
+  }
+ ],
+ "has_web_view": 0,
+ "hide_heading": 0,
+ "hide_toolbar": 0,
+ "idx": 0,
+ "image_view": 0,
+ "in_create": 0,
+ "is_submittable": 0,
+ "issingle": 0,
+ "istable": 0,
+ "max_attachments": 0,
+ "modified": "2018-10-25 15:47:03.841390",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "Bank Account Subtype",
+ "name_case": "",
+ "owner": "Administrator",
+ "permissions": [
+  {
+   "amend": 0,
+   "cancel": 0,
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "export": 1,
+   "if_owner": 0,
+   "import": 0,
+   "permlevel": 0,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "System Manager",
+   "set_user_permissions": 0,
+   "share": 1,
+   "submit": 0,
+   "write": 1
+  },
+  {
+   "amend": 0,
+   "cancel": 0,
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "export": 1,
+   "if_owner": 0,
+   "import": 0,
+   "permlevel": 0,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "Accounts Manager",
+   "set_user_permissions": 0,
+   "share": 1,
+   "submit": 0,
+   "write": 1
+  },
+  {
+   "amend": 0,
+   "cancel": 0,
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "export": 1,
+   "if_owner": 0,
+   "import": 0,
+   "permlevel": 0,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "Accounts User",
+   "set_user_permissions": 0,
+   "share": 1,
+   "submit": 0,
+   "write": 1
+  }
+ ],
+ "quick_entry": 1,
+ "read_only": 0,
+ "read_only_onload": 0,
+ "show_name_in_global_search": 0,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 0,
+ "track_seen": 0,
+ "track_views": 0
+}
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/account_subtype/account_subtype.py b/erpnext/accounts/doctype/bank_account_subtype/bank_account_subtype.py
similarity index 86%
rename from erpnext/accounts/doctype/account_subtype/account_subtype.py
rename to erpnext/accounts/doctype/bank_account_subtype/bank_account_subtype.py
index 46c45cc..ab52c4a 100644
--- a/erpnext/accounts/doctype/account_subtype/account_subtype.py
+++ b/erpnext/accounts/doctype/bank_account_subtype/bank_account_subtype.py
@@ -5,5 +5,5 @@
 from __future__ import unicode_literals
 from frappe.model.document import Document
 
-class AccountSubtype(Document):
+class BankAccountSubtype(Document):
 	pass
diff --git a/erpnext/accounts/doctype/account_subtype/test_account_subtype.js b/erpnext/accounts/doctype/bank_account_subtype/test_bank_account_subtype.js
similarity index 69%
rename from erpnext/accounts/doctype/account_subtype/test_account_subtype.js
rename to erpnext/accounts/doctype/bank_account_subtype/test_bank_account_subtype.js
index 5646763..f599998 100644
--- a/erpnext/accounts/doctype/account_subtype/test_account_subtype.js
+++ b/erpnext/accounts/doctype/bank_account_subtype/test_bank_account_subtype.js
@@ -2,15 +2,15 @@
 // rename this file from _test_[name] to test_[name] to activate
 // and remove above this line
 
-QUnit.test("test: Account Subtype", function (assert) {
+QUnit.test("test: Bank Account Subtype", function (assert) {
 	let done = assert.async();
 
 	// number of asserts
 	assert.expect(1);
 
 	frappe.run_serially([
-		// insert a new Account Subtype
-		() => frappe.tests.make('Account Subtype', [
+		// insert a new Bank Account Subtype
+		() => frappe.tests.make('Bank Account Subtype', [
 			// values to be set
 			{key: 'value'}
 		]),
diff --git a/erpnext/accounts/doctype/bank_reconciliation/test_bank_reconciliation.py b/erpnext/accounts/doctype/bank_account_subtype/test_bank_account_subtype.py
similarity index 77%
rename from erpnext/accounts/doctype/bank_reconciliation/test_bank_reconciliation.py
rename to erpnext/accounts/doctype/bank_account_subtype/test_bank_account_subtype.py
index 932fb33..ca3addc 100644
--- a/erpnext/accounts/doctype/bank_reconciliation/test_bank_reconciliation.py
+++ b/erpnext/accounts/doctype/bank_account_subtype/test_bank_account_subtype.py
@@ -2,7 +2,8 @@
 # Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
 # See license.txt
 from __future__ import unicode_literals
+
 import unittest
 
-class TestBankReconciliation(unittest.TestCase):
+class TestBankAccountSubtype(unittest.TestCase):
 	pass
diff --git a/erpnext/accounts/doctype/account_type/__init__.py b/erpnext/accounts/doctype/bank_account_type/__init__.py
similarity index 100%
rename from erpnext/accounts/doctype/account_type/__init__.py
rename to erpnext/accounts/doctype/bank_account_type/__init__.py
diff --git a/erpnext/accounts/doctype/bank_account_type/bank_account_type.js b/erpnext/accounts/doctype/bank_account_type/bank_account_type.js
new file mode 100644
index 0000000..4cfabe3
--- /dev/null
+++ b/erpnext/accounts/doctype/bank_account_type/bank_account_type.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('Bank Account Type', {
+	// refresh: function(frm) {
+
+	// }
+});
diff --git a/erpnext/accounts/doctype/bank_account_type/bank_account_type.json b/erpnext/accounts/doctype/bank_account_type/bank_account_type.json
new file mode 100644
index 0000000..5a297cc
--- /dev/null
+++ b/erpnext/accounts/doctype/bank_account_type/bank_account_type.json
@@ -0,0 +1,68 @@
+{
+ "actions": [],
+ "allow_import": 1,
+ "allow_rename": 1,
+ "autoname": "field:account_type",
+ "creation": "2018-10-25 15:45:45.789963",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "account_type"
+ ],
+ "fields": [
+  {
+   "fieldname": "account_type",
+   "fieldtype": "Data",
+   "label": "Account Type",
+   "unique": 1
+  }
+ ],
+ "links": [],
+ "modified": "2020-04-10 21:13:09.137898",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "Bank Account Type",
+ "owner": "Administrator",
+ "permissions": [
+  {
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "export": 1,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "System Manager",
+   "share": 1,
+   "write": 1
+  },
+  {
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "export": 1,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "Accounts Manager",
+   "share": 1,
+   "write": 1
+  },
+  {
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "export": 1,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "Accounts User",
+   "share": 1,
+   "write": 1
+  }
+ ],
+ "quick_entry": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC"
+}
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/account_type/account_type.py b/erpnext/accounts/doctype/bank_account_type/bank_account_type.py
similarity index 60%
rename from erpnext/accounts/doctype/account_type/account_type.py
rename to erpnext/accounts/doctype/bank_account_type/bank_account_type.py
index 3e64293..b7dc0e0 100644
--- a/erpnext/accounts/doctype/account_type/account_type.py
+++ b/erpnext/accounts/doctype/bank_account_type/bank_account_type.py
@@ -1,9 +1,10 @@
 # -*- coding: utf-8 -*-
-# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
+# 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 AccountType(Document):
+class BankAccountType(Document):
 	pass
diff --git a/erpnext/accounts/doctype/bank_account_type/test_bank_account_type.py b/erpnext/accounts/doctype/bank_account_type/test_bank_account_type.py
new file mode 100644
index 0000000..f04725a
--- /dev/null
+++ b/erpnext/accounts/doctype/bank_account_type/test_bank_account_type.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 TestBankAccountType(unittest.TestCase):
+	pass
diff --git a/erpnext/accounts/doctype/bank_reconciliation/README.md b/erpnext/accounts/doctype/bank_clearance/README.md
similarity index 100%
rename from erpnext/accounts/doctype/bank_reconciliation/README.md
rename to erpnext/accounts/doctype/bank_clearance/README.md
diff --git a/erpnext/accounts/doctype/account_subtype/__init__.py b/erpnext/accounts/doctype/bank_clearance/__init__.py
similarity index 100%
copy from erpnext/accounts/doctype/account_subtype/__init__.py
copy to erpnext/accounts/doctype/bank_clearance/__init__.py
diff --git a/erpnext/accounts/doctype/bank_reconciliation/bank_reconciliation.js b/erpnext/accounts/doctype/bank_clearance/bank_clearance.js
similarity index 96%
rename from erpnext/accounts/doctype/bank_reconciliation/bank_reconciliation.js
rename to erpnext/accounts/doctype/bank_clearance/bank_clearance.js
index 19fadbf..ba3f2fa 100644
--- a/erpnext/accounts/doctype/bank_reconciliation/bank_reconciliation.js
+++ b/erpnext/accounts/doctype/bank_clearance/bank_clearance.js
@@ -1,7 +1,7 @@
 // Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
 // License: GNU General Public License v3. See license.txt
 
-frappe.ui.form.on("Bank Reconciliation", {
+frappe.ui.form.on("Bank Clearance", {
 	setup: function(frm) {
 		frm.add_fetch("account", "account_currency", "account_currency");
 	},
diff --git a/erpnext/accounts/doctype/bank_clearance/bank_clearance.json b/erpnext/accounts/doctype/bank_clearance/bank_clearance.json
new file mode 100644
index 0000000..a436d1e
--- /dev/null
+++ b/erpnext/accounts/doctype/bank_clearance/bank_clearance.json
@@ -0,0 +1,130 @@
+{
+ "allow_copy": 1,
+ "creation": "2013-01-10 16:34:05",
+ "doctype": "DocType",
+ "document_type": "Document",
+ "engine": "InnoDB",
+ "field_order": [
+  "account",
+  "account_currency",
+  "from_date",
+  "to_date",
+  "column_break_5",
+  "bank_account",
+  "include_reconciled_entries",
+  "include_pos_transactions",
+  "get_payment_entries",
+  "section_break_10",
+  "payment_entries",
+  "update_clearance_date",
+  "total_amount"
+ ],
+ "fields": [
+  {
+   "fetch_from": "bank_account.account",
+   "fetch_if_empty": 1,
+   "fieldname": "account",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "label": "Account",
+   "options": "Account",
+   "reqd": 1
+  },
+  {
+   "fieldname": "account_currency",
+   "fieldtype": "Link",
+   "hidden": 1,
+   "label": "Account Currency",
+   "options": "Currency",
+   "print_hide": 1
+  },
+  {
+   "fieldname": "from_date",
+   "fieldtype": "Date",
+   "in_list_view": 1,
+   "label": "From Date",
+   "reqd": 1
+  },
+  {
+   "fieldname": "to_date",
+   "fieldtype": "Date",
+   "in_list_view": 1,
+   "label": "To Date",
+   "reqd": 1
+  },
+  {
+   "fieldname": "column_break_5",
+   "fieldtype": "Column Break"
+  },
+  {
+   "description": "Select the Bank Account to reconcile.",
+   "fieldname": "bank_account",
+   "fieldtype": "Link",
+   "label": "Bank Account",
+   "options": "Bank Account"
+  },
+  {
+   "default": "0",
+   "fieldname": "include_reconciled_entries",
+   "fieldtype": "Check",
+   "in_list_view": 1,
+   "label": "Include Reconciled Entries"
+  },
+  {
+   "default": "0",
+   "fieldname": "include_pos_transactions",
+   "fieldtype": "Check",
+   "label": "Include POS Transactions"
+  },
+  {
+   "fieldname": "get_payment_entries",
+   "fieldtype": "Button",
+   "label": "Get Payment Entries"
+  },
+  {
+   "fieldname": "section_break_10",
+   "fieldtype": "Section Break"
+  },
+  {
+   "allow_bulk_edit": 1,
+   "fieldname": "payment_entries",
+   "fieldtype": "Table",
+   "label": "Payment Entries",
+   "options": "Bank Clearance Detail"
+  },
+  {
+   "fieldname": "update_clearance_date",
+   "fieldtype": "Button",
+   "label": "Update Clearance Date"
+  },
+  {
+   "fieldname": "total_amount",
+   "fieldtype": "Currency",
+   "label": "Total Amount",
+   "options": "account_currency",
+   "read_only": 1
+  }
+ ],
+ "hide_toolbar": 1,
+ "icon": "fa fa-check",
+ "idx": 1,
+ "issingle": 1,
+ "modified": "2020-04-06 16:12:06.628008",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "Bank Clearance",
+ "owner": "Administrator",
+ "permissions": [
+  {
+   "create": 1,
+   "read": 1,
+   "role": "Accounts User",
+   "share": 1,
+   "write": 1
+  }
+ ],
+ "quick_entry": 1,
+ "read_only": 1,
+ "sort_field": "modified",
+ "sort_order": "ASC"
+}
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/bank_reconciliation/bank_reconciliation.py b/erpnext/accounts/doctype/bank_clearance/bank_clearance.py
similarity index 98%
rename from erpnext/accounts/doctype/bank_reconciliation/bank_reconciliation.py
rename to erpnext/accounts/doctype/bank_clearance/bank_clearance.py
index 48fd154..6fec3ab 100644
--- a/erpnext/accounts/doctype/bank_reconciliation/bank_reconciliation.py
+++ b/erpnext/accounts/doctype/bank_clearance/bank_clearance.py
@@ -11,7 +11,7 @@
 	"journal_entries": "templates/form_grid/bank_reconciliation_grid.html"
 }
 
-class BankReconciliation(Document):
+class BankClearance(Document):
 	def get_payment_entries(self):
 		if not (self.from_date and self.to_date):
 			frappe.throw(_("From Date and To Date are Mandatory"))
diff --git a/erpnext/accounts/doctype/bank_clearance/test_bank_clearance.py b/erpnext/accounts/doctype/bank_clearance/test_bank_clearance.py
new file mode 100644
index 0000000..833abde
--- /dev/null
+++ b/erpnext/accounts/doctype/bank_clearance/test_bank_clearance.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 TestBankClearance(unittest.TestCase):
+	pass
diff --git a/erpnext/accounts/doctype/bank_clearance_detail/README.md b/erpnext/accounts/doctype/bank_clearance_detail/README.md
new file mode 100644
index 0000000..ee83a44
--- /dev/null
+++ b/erpnext/accounts/doctype/bank_clearance_detail/README.md
@@ -0,0 +1 @@
+Detail of transaction for parent Bank Clearance.
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/bank_reconciliation_detail/__init__.py b/erpnext/accounts/doctype/bank_clearance_detail/__init__.py
similarity index 100%
rename from erpnext/accounts/doctype/bank_reconciliation_detail/__init__.py
rename to erpnext/accounts/doctype/bank_clearance_detail/__init__.py
diff --git a/erpnext/accounts/doctype/bank_reconciliation_detail/bank_reconciliation_detail.json b/erpnext/accounts/doctype/bank_clearance_detail/bank_clearance_detail.json
similarity index 98%
rename from erpnext/accounts/doctype/bank_reconciliation_detail/bank_reconciliation_detail.json
rename to erpnext/accounts/doctype/bank_clearance_detail/bank_clearance_detail.json
index 183068c..04988bf 100644
--- a/erpnext/accounts/doctype/bank_reconciliation_detail/bank_reconciliation_detail.json
+++ b/erpnext/accounts/doctype/bank_clearance_detail/bank_clearance_detail.json
@@ -326,7 +326,7 @@
  "modified": "2019-01-07 16:52:07.174687", 
  "modified_by": "Administrator", 
  "module": "Accounts", 
- "name": "Bank Reconciliation Detail", 
+ "name": "Bank Clearance Detail", 
  "owner": "Administrator", 
  "permissions": [], 
  "quick_entry": 1, 
diff --git a/erpnext/accounts/doctype/bank_reconciliation_detail/bank_reconciliation_detail.py b/erpnext/accounts/doctype/bank_clearance_detail/bank_clearance_detail.py
similarity index 84%
rename from erpnext/accounts/doctype/bank_reconciliation_detail/bank_reconciliation_detail.py
rename to erpnext/accounts/doctype/bank_clearance_detail/bank_clearance_detail.py
index 990b2a6..ecc5367 100644
--- a/erpnext/accounts/doctype/bank_reconciliation_detail/bank_reconciliation_detail.py
+++ b/erpnext/accounts/doctype/bank_clearance_detail/bank_clearance_detail.py
@@ -5,5 +5,5 @@
 import frappe
 from frappe.model.document import Document
 
-class BankReconciliationDetail(Document):
+class BankClearanceDetail(Document):
 	pass
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/bank_reconciliation/__init__.py b/erpnext/accounts/doctype/bank_reconciliation/__init__.py
deleted file mode 100644
index baffc48..0000000
--- a/erpnext/accounts/doctype/bank_reconciliation/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-from __future__ import unicode_literals
diff --git a/erpnext/accounts/doctype/bank_reconciliation/bank_reconciliation.json b/erpnext/accounts/doctype/bank_reconciliation/bank_reconciliation.json
deleted file mode 100644
index b85ef3e..0000000
--- a/erpnext/accounts/doctype/bank_reconciliation/bank_reconciliation.json
+++ /dev/null
@@ -1,484 +0,0 @@
-{
- "allow_copy": 1, 
- "allow_events_in_timeline": 0, 
- "allow_guest_to_view": 0, 
- "allow_import": 0, 
- "allow_rename": 0, 
- "beta": 0, 
- "creation": "2013-01-10 16:34:05", 
- "custom": 0, 
- "docstatus": 0, 
- "doctype": "DocType", 
- "document_type": "Document", 
- "editable_grid": 0, 
- "fields": [
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fetch_from": "bank_account.account", 
-   "fetch_if_empty": 1, 
-   "fieldname": "account", 
-   "fieldtype": "Link", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Account", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Account", 
-   "permlevel": 0, 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 1, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fetch_if_empty": 0, 
-   "fieldname": "account_currency", 
-   "fieldtype": "Link", 
-   "hidden": 1, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Account Currency", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Currency", 
-   "permlevel": 0, 
-   "print_hide": 1, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fetch_if_empty": 0, 
-   "fieldname": "from_date", 
-   "fieldtype": "Date", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "From Date", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 1, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fetch_if_empty": 0, 
-   "fieldname": "to_date", 
-   "fieldtype": "Date", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "To Date", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 1, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fetch_if_empty": 0, 
-   "fieldname": "column_break_5", 
-   "fieldtype": "Column Break", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "description": "Select the Bank Account to reconcile.",
-   "fetch_if_empty": 0, 
-   "fieldname": "bank_account", 
-   "fieldtype": "Link", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Bank Account", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Bank Account", 
-   "permlevel": 0, 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fetch_if_empty": 0, 
-   "fieldname": "include_reconciled_entries", 
-   "fieldtype": "Check", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Include Reconciled Entries", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fetch_if_empty": 0, 
-   "fieldname": "include_pos_transactions", 
-   "fieldtype": "Check", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Include POS Transactions", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fetch_if_empty": 0, 
-   "fieldname": "get_payment_entries", 
-   "fieldtype": "Button", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Get Payment Entries", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "", 
-   "permlevel": 0, 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fetch_if_empty": 0, 
-   "fieldname": "section_break_10", 
-   "fieldtype": "Section Break", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 1, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fetch_if_empty": 0, 
-   "fieldname": "payment_entries", 
-   "fieldtype": "Table", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Payment Entries", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Bank Reconciliation Detail", 
-   "permlevel": 0, 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fetch_if_empty": 0, 
-   "fieldname": "update_clearance_date", 
-   "fieldtype": "Button", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Update Clearance Date", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "", 
-   "permlevel": 0, 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fetch_if_empty": 0, 
-   "fieldname": "total_amount", 
-   "fieldtype": "Currency", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Total Amount", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "account_currency", 
-   "permlevel": 0, 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 1, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }
- ], 
- "has_web_view": 0, 
- "hide_toolbar": 1, 
- "icon": "fa fa-check", 
- "idx": 1, 
- "in_create": 0, 
- "is_submittable": 0, 
- "issingle": 1, 
- "istable": 0, 
- "max_attachments": 0, 
- "menu_index": 0, 
- "modified": "2020-01-22 00:00:00.000000", 
- "modified_by": "Administrator", 
- "module": "Accounts", 
- "name": "Bank Reconciliation", 
- "owner": "Administrator", 
- "permissions": [
-  {
-   "amend": 0, 
-   "cancel": 0, 
-   "create": 1, 
-   "delete": 0, 
-   "email": 0, 
-   "export": 0, 
-   "if_owner": 0, 
-   "import": 0, 
-   "permlevel": 0, 
-   "print": 0, 
-   "read": 1, 
-   "report": 0, 
-   "role": "Accounts User", 
-   "set_user_permissions": 0, 
-   "share": 1, 
-   "submit": 0, 
-   "write": 1
-  }
- ], 
- "quick_entry": 1, 
- "read_only": 1, 
- "show_name_in_global_search": 0, 
- "sort_order": "ASC", 
- "track_changes": 0, 
- "track_seen": 0, 
- "track_views": 0
-}
diff --git a/erpnext/accounts/doctype/bank_reconciliation/test_bank_reconciliation.js b/erpnext/accounts/doctype/bank_reconciliation/test_bank_reconciliation.js
deleted file mode 100644
index f52f6fb..0000000
--- a/erpnext/accounts/doctype/bank_reconciliation/test_bank_reconciliation.js
+++ /dev/null
@@ -1,22 +0,0 @@
-QUnit.module('Account');
-
-QUnit.test("test Bank Reconciliation", function(assert) {
-	assert.expect(0);
-	let done = assert.async();
-	frappe.run_serially([
-		() => frappe.set_route('Form', 'Bank Reconciliation'),
-		() => cur_frm.set_value('bank_account','Cash - FT'),
-		() => frappe.click_button('Get Payment Entries'),
-		() => {
-			for(var i=0;i<=cur_frm.doc.payment_entries.length-1;i++){
-				cur_frm.doc.payment_entries[i].clearance_date = frappe.datetime.add_days(frappe.datetime.now_date(), 2);
-			}
-		},
-		() => {cur_frm.refresh_fields('payment_entries');},
-		() => frappe.click_button('Update Clearance Date'),
-		() => frappe.timeout(0.5),
-		() => frappe.click_button('Close'),
-		() => done()
-	]);
-});
-
diff --git a/erpnext/accounts/doctype/bank_reconciliation_detail/README.md b/erpnext/accounts/doctype/bank_reconciliation_detail/README.md
deleted file mode 100644
index 07d0731..0000000
--- a/erpnext/accounts/doctype/bank_reconciliation_detail/README.md
+++ /dev/null
@@ -1 +0,0 @@
-Detail of transaction for parent Bank Reconciliation.
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/budget/budget.py b/erpnext/accounts/doctype/budget/budget.py
index 084514c..d93b6ff 100644
--- a/erpnext/accounts/doctype/budget/budget.py
+++ b/erpnext/accounts/doctype/budget/budget.py
@@ -9,6 +9,7 @@
 from frappe.model.naming import make_autoname
 from erpnext.accounts.utils import get_fiscal_year
 from frappe.model.document import Document
+from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_accounting_dimensions
 
 class BudgetError(frappe.ValidationError): pass
 class DuplicateBudgetError(frappe.ValidationError): pass
@@ -98,30 +99,32 @@
 	if not (args.get('account') and args.get('cost_center')) and args.item_code:
 		args.cost_center, args.account = get_item_details(args)
 
-	if not (args.cost_center or args.project) and not args.account:
+	if not args.account:
 		return
 
-	for budget_against in ['project', 'cost_center']:
+	for budget_against in ['project', 'cost_center'] + get_accounting_dimensions():
 		if (args.get(budget_against) and args.account
 				and frappe.db.get_value("Account", {"name": args.account, "root_type": "Expense"})):
 
-			if args.project and budget_against == 'project':
-				condition = "and b.project=%s" % frappe.db.escape(args.project)
-				args.budget_against_field = "Project"
+			doctype = frappe.unscrub(budget_against)
 
-			elif args.cost_center and budget_against == 'cost_center':
-				cc_lft, cc_rgt = frappe.db.get_value("Cost Center", args.cost_center, ["lft", "rgt"])
-				condition = """and exists(select name from `tabCost Center`
-					where lft<=%s and rgt>=%s and name=b.cost_center)""" % (cc_lft, cc_rgt)
-				args.budget_against_field = "Cost Center"
+			if frappe.get_cached_value('DocType', doctype, 'is_tree'):
+				lft, rgt = frappe.db.get_value(doctype, args.get(budget_against), ["lft", "rgt"])
+				condition = """and exists(select name from `tab%s`
+					where lft<=%s and rgt>=%s and name=b.%s)""" % (doctype, lft, rgt, budget_against) #nosec
+				args.is_tree = True
+			else:
+				condition = "and b.%s=%s" % (budget_against, frappe.db.escape(args.get(budget_against)))
+				args.is_tree = False
 
-			args.budget_against = args.get(budget_against)
+			args.budget_against_field = budget_against
+			args.budget_against_doctype = doctype
 
 			budget_records = frappe.db.sql("""
 				select
 					b.{budget_against_field} as budget_against, ba.budget_amount, b.monthly_distribution,
 					ifnull(b.applicable_on_material_request, 0) as for_material_request,
-					ifnull(applicable_on_purchase_order,0) as for_purchase_order,
+					ifnull(applicable_on_purchase_order, 0) as for_purchase_order,
 					ifnull(applicable_on_booking_actual_expenses,0) as for_actual_expenses,
 					b.action_if_annual_budget_exceeded, b.action_if_accumulated_monthly_budget_exceeded,
 					b.action_if_annual_budget_exceeded_on_mr, b.action_if_accumulated_monthly_budget_exceeded_on_mr,
@@ -132,9 +135,7 @@
 					b.name=ba.parent and b.fiscal_year=%s
 					and ba.account=%s and b.docstatus=1
 					{condition}
-			""".format(condition=condition,
-				budget_against_field=frappe.scrub(args.get("budget_against_field"))),
-				(args.fiscal_year, args.account), as_dict=True)
+			""".format(condition=condition, budget_against_field=budget_against), (args.fiscal_year, args.account), as_dict=True) #nosec
 
 			if budget_records:
 				validate_budget_records(args, budget_records)
@@ -230,10 +231,10 @@
 
 def get_other_condition(args, budget, for_doc):
 	condition = "expense_account = '%s'" % (args.expense_account)
-	budget_against_field = frappe.scrub(args.get("budget_against_field"))
+	budget_against_field = args.get("budget_against_field")
 
 	if budget_against_field and args.get(budget_against_field):
-		condition += " and child.%s = '%s'" %(budget_against_field, args.get(budget_against_field))
+		condition += " and child.%s = '%s'" % (budget_against_field, args.get(budget_against_field))
 
 	if args.get('fiscal_year'):
 		date_field = 'schedule_date' if for_doc == 'Material Request' else 'transaction_date'
@@ -246,19 +247,30 @@
 	return condition
 
 def get_actual_expense(args):
+	if not args.budget_against_doctype:
+		args.budget_against_doctype = frappe.unscrub(args.budget_against_field)
+
+	budget_against_field = args.get('budget_against_field')
 	condition1 = " and gle.posting_date <= %(month_end_date)s" \
 		if args.get("month_end_date") else ""
-	if args.budget_against_field == "Cost Center":
-		lft_rgt = frappe.db.get_value(args.budget_against_field,
-			args.budget_against, ["lft", "rgt"], as_dict=1)
+
+	if args.is_tree:
+		lft_rgt = frappe.db.get_value(args.budget_against_doctype,
+			args.get(budget_against_field), ["lft", "rgt"], as_dict=1)
+
 		args.update(lft_rgt)
-		condition2 = """and exists(select name from `tabCost Center`
-			where lft>=%(lft)s and rgt<=%(rgt)s and name=gle.cost_center)"""
 
-	elif args.budget_against_field == "Project":
-		condition2 = "and exists(select name from `tabProject` where name=gle.project and gle.project = %(budget_against)s)"
+		condition2 = """and exists(select name from `tab{doctype}`
+			where lft>=%(lft)s and rgt<=%(rgt)s
+			and name=gle.{budget_against_field})""".format(doctype=args.budget_against_doctype, #nosec
+			budget_against_field=budget_against_field)
+	else:
+		condition2 = """and exists(select name from `tab{doctype}`
+		where name=gle.{budget_against} and
+		gle.{budget_against} = %({budget_against})s)""".format(doctype=args.budget_against_doctype,
+		budget_against = budget_against_field)
 
-	return flt(frappe.db.sql("""
+	amount  = flt(frappe.db.sql("""
 		select sum(gle.debit) - sum(gle.credit)
 		from `tabGL Entry` gle
 		where gle.account=%(account)s
@@ -267,7 +279,9 @@
 			and gle.company=%(company)s
 			and gle.docstatus=1
 			{condition2}
-	""".format(condition1=condition1, condition2=condition2), (args))[0][0])
+	""".format(condition1=condition1, condition2=condition2), (args))[0][0]) #nosec
+
+	return amount
 
 def get_accumulated_monthly_budget(monthly_distribution, posting_date, fiscal_year, annual_budget):
 	distribution = {}
diff --git a/erpnext/accounts/doctype/budget/test_budget.py b/erpnext/accounts/doctype/budget/test_budget.py
index 33aefd6..61c48c7 100644
--- a/erpnext/accounts/doctype/budget/test_budget.py
+++ b/erpnext/accounts/doctype/budget/test_budget.py
@@ -5,7 +5,7 @@
 
 import frappe
 import unittest
-from frappe.utils import nowdate
+from frappe.utils import nowdate, now_datetime
 from erpnext.accounts.utils import get_fiscal_year
 from erpnext.buying.doctype.purchase_order.test_purchase_order import create_purchase_order
 from erpnext.accounts.doctype.budget.budget import get_actual_expense, BudgetError
@@ -13,27 +13,28 @@
 
 class TestBudget(unittest.TestCase):
 	def test_monthly_budget_crossed_ignore(self):
-		set_total_expense_zero("2013-02-28", "Cost Center")
+		set_total_expense_zero(nowdate(), "cost_center")
 
 		budget = make_budget(budget_against="Cost Center")
 
 		jv = make_journal_entry("_Test Account Cost for Goods Sold - _TC",
-			"_Test Bank - _TC", 40000, "_Test Cost Center - _TC", posting_date="2013-02-28", submit=True)
+			"_Test Bank - _TC", 40000, "_Test Cost Center - _TC", posting_date=nowdate(), submit=True)
 
 		self.assertTrue(frappe.db.get_value("GL Entry",
 			{"voucher_type": "Journal Entry", "voucher_no": jv.name}))
 
 		budget.cancel()
+		jv.cancel()
 
 	def test_monthly_budget_crossed_stop1(self):
-		set_total_expense_zero("2013-02-28", "Cost Center")
+		set_total_expense_zero(nowdate(), "cost_center")
 
 		budget = make_budget(budget_against="Cost Center")
 
 		frappe.db.set_value("Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop")
 
 		jv = make_journal_entry("_Test Account Cost for Goods Sold - _TC",
-			"_Test Bank - _TC", 40000, "_Test Cost Center - _TC", posting_date="2013-02-28")
+			"_Test Bank - _TC", 40000, "_Test Cost Center - _TC", posting_date=nowdate())
 
 		self.assertRaises(BudgetError, jv.submit)
 
@@ -41,14 +42,14 @@
 		budget.cancel()
 
 	def test_exception_approver_role(self):
-		set_total_expense_zero("2013-02-28", "Cost Center")
+		set_total_expense_zero(nowdate(), "cost_center")
 
 		budget = make_budget(budget_against="Cost Center")
 
 		frappe.db.set_value("Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop")
 
 		jv = make_journal_entry("_Test Account Cost for Goods Sold - _TC",
-			"_Test Bank - _TC", 40000, "_Test Cost Center - _TC", posting_date="2013-03-02")
+			"_Test Bank - _TC", 40000, "_Test Cost Center - _TC", posting_date=nowdate())
 
 		self.assertRaises(BudgetError, jv.submit)
 
@@ -112,16 +113,17 @@
 
 		budget.load_from_db()
 		budget.cancel()
+		po.cancel()
 
 	def test_monthly_budget_crossed_stop2(self):
-		set_total_expense_zero("2013-02-28", "Project")
+		set_total_expense_zero(nowdate(), "project")
 
 		budget = make_budget(budget_against="Project")
 
 		frappe.db.set_value("Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop")
 
 		jv = make_journal_entry("_Test Account Cost for Goods Sold - _TC",
-			"_Test Bank - _TC", 40000, "_Test Cost Center - _TC", project="_Test Project", posting_date="2013-02-28")
+			"_Test Bank - _TC", 40000, "_Test Cost Center - _TC", project="_Test Project", posting_date=nowdate())
 
 		self.assertRaises(BudgetError, jv.submit)
 
@@ -129,86 +131,76 @@
 		budget.cancel()
 
 	def test_yearly_budget_crossed_stop1(self):
-		set_total_expense_zero("2013-02-28", "Cost Center")
+		set_total_expense_zero(nowdate(), "cost_center")
 
 		budget = make_budget(budget_against="Cost Center")
 
 		jv = make_journal_entry("_Test Account Cost for Goods Sold - _TC",
-			"_Test Bank - _TC", 150000, "_Test Cost Center - _TC", posting_date="2013-03-28")
+			"_Test Bank - _TC", 250000, "_Test Cost Center - _TC", posting_date=nowdate())
 
 		self.assertRaises(BudgetError, jv.submit)
 
 		budget.cancel()
 
 	def test_yearly_budget_crossed_stop2(self):
-		set_total_expense_zero("2013-02-28", "Project")
+		set_total_expense_zero(nowdate(), "project")
 
 		budget = make_budget(budget_against="Project")
 
 		jv = make_journal_entry("_Test Account Cost for Goods Sold - _TC",
-			"_Test Bank - _TC", 150000, "_Test Cost Center - _TC", project="_Test Project", posting_date="2013-03-28")
+			"_Test Bank - _TC", 250000, "_Test Cost Center - _TC", project="_Test Project", posting_date=nowdate())
 
 		self.assertRaises(BudgetError, jv.submit)
 
 		budget.cancel()
 
 	def test_monthly_budget_on_cancellation1(self):
-		set_total_expense_zero("2013-02-28", "Cost Center")
+		set_total_expense_zero(nowdate(), "cost_center")
 
 		budget = make_budget(budget_against="Cost Center")
 
-		jv1 = make_journal_entry("_Test Account Cost for Goods Sold - _TC",
-			"_Test Bank - _TC", 20000, "_Test Cost Center - _TC", posting_date="2013-02-28", submit=True)
+		for i in range(now_datetime().month):
+			jv = make_journal_entry("_Test Account Cost for Goods Sold - _TC",
+				"_Test Bank - _TC", 20000, "_Test Cost Center - _TC", posting_date=nowdate(), submit=True)
 
-		self.assertTrue(frappe.db.get_value("GL Entry",
-			{"voucher_type": "Journal Entry", "voucher_no": jv1.name}))
-
-		jv2 = make_journal_entry("_Test Account Cost for Goods Sold - _TC",
-			"_Test Bank - _TC", 20000, "_Test Cost Center - _TC", posting_date="2013-02-28", submit=True)
-
-		self.assertTrue(frappe.db.get_value("GL Entry",
-			{"voucher_type": "Journal Entry", "voucher_no": jv2.name}))
+			self.assertTrue(frappe.db.get_value("GL Entry",
+				{"voucher_type": "Journal Entry", "voucher_no": jv.name}))
 
 		frappe.db.set_value("Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop")
 
-		self.assertRaises(BudgetError, jv1.cancel)
+		self.assertRaises(BudgetError, jv.cancel)
 
 		budget.load_from_db()
 		budget.cancel()
 
 	def test_monthly_budget_on_cancellation2(self):
-		set_total_expense_zero("2013-02-28", "Project")
+		set_total_expense_zero(nowdate(), "project")
 
 		budget = make_budget(budget_against="Project")
 
-		jv1 = make_journal_entry("_Test Account Cost for Goods Sold - _TC",
-			"_Test Bank - _TC", 20000, "_Test Cost Center - _TC", posting_date="2013-02-28", submit=True, project="_Test Project")
+		for i in range(now_datetime().month):
+			jv = make_journal_entry("_Test Account Cost for Goods Sold - _TC",
+				"_Test Bank - _TC", 20000, "_Test Cost Center - _TC", posting_date=nowdate(), submit=True, project="_Test Project")
 
-		self.assertTrue(frappe.db.get_value("GL Entry",
-			{"voucher_type": "Journal Entry", "voucher_no": jv1.name}))
-
-		jv2 = make_journal_entry("_Test Account Cost for Goods Sold - _TC",
-			"_Test Bank - _TC", 20000, "_Test Cost Center - _TC", posting_date="2013-02-28", submit=True, project="_Test Project")
-
-		self.assertTrue(frappe.db.get_value("GL Entry",
-			{"voucher_type": "Journal Entry", "voucher_no": jv2.name}))
+			self.assertTrue(frappe.db.get_value("GL Entry",
+				{"voucher_type": "Journal Entry", "voucher_no": jv.name}))
 
 		frappe.db.set_value("Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop")
 
-		self.assertRaises(BudgetError, jv1.cancel)
+		self.assertRaises(BudgetError, jv.cancel)
 
 		budget.load_from_db()
 		budget.cancel()
 
 	def test_monthly_budget_against_group_cost_center(self):
-		set_total_expense_zero("2013-02-28", "Cost Center")
-		set_total_expense_zero("2013-02-28", "Cost Center", "_Test Cost Center 2 - _TC")
+		set_total_expense_zero(nowdate(), "cost_center")
+		set_total_expense_zero(nowdate(), "cost_center", "_Test Cost Center 2 - _TC")
 
 		budget = make_budget(budget_against="Cost Center", cost_center="_Test Company - _TC")
 		frappe.db.set_value("Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop")
 
 		jv = make_journal_entry("_Test Account Cost for Goods Sold - _TC",
-			"_Test Bank - _TC", 40000, "_Test Cost Center 2 - _TC", posting_date="2013-02-28")
+			"_Test Bank - _TC", 40000, "_Test Cost Center 2 - _TC", posting_date=nowdate())
 
 		self.assertRaises(BudgetError, jv.submit)
 
@@ -231,7 +223,7 @@
 		frappe.db.set_value("Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop")
 
 		jv = make_journal_entry("_Test Account Cost for Goods Sold - _TC",
-			"_Test Bank - _TC", 40000, cost_center, posting_date="2013-02-28")
+			"_Test Bank - _TC", 40000, cost_center, posting_date=nowdate())
 
 		self.assertRaises(BudgetError, jv.submit)
 
@@ -241,27 +233,34 @@
 
 
 def set_total_expense_zero(posting_date, budget_against_field=None, budget_against_CC=None):
-	if budget_against_field == "Project":
+	if budget_against_field == "project":
 		budget_against = "_Test Project"
 	else:
 		budget_against = budget_against_CC or "_Test Cost Center - _TC"
-	existing_expense = get_actual_expense(frappe._dict({
+
+	fiscal_year = get_fiscal_year(nowdate())[0]
+
+	args = frappe._dict({
 		"account": "_Test Account Cost for Goods Sold - _TC",
 		"cost_center": "_Test Cost Center - _TC",
 		"monthly_end_date": posting_date,
 		"company": "_Test Company",
-		"fiscal_year": "_Test Fiscal Year 2013",
+		"fiscal_year": fiscal_year,
 		"budget_against_field": budget_against_field,
-		"budget_against": budget_against
-	}))
+	})
+
+	if not args.get(budget_against_field):
+		args[budget_against_field] = budget_against
+
+	existing_expense = get_actual_expense(args)
 
 	if existing_expense:
-		if budget_against_field == "Cost Center":
+		if budget_against_field == "cost_center":
 			make_journal_entry("_Test Account Cost for Goods Sold - _TC",
-			"_Test Bank - _TC", -existing_expense, "_Test Cost Center - _TC", posting_date="2013-02-28", submit=True)
-		elif budget_against_field == "Project":
+			"_Test Bank - _TC", -existing_expense, "_Test Cost Center - _TC", posting_date=nowdate(), submit=True)
+		elif budget_against_field == "project":
 			make_journal_entry("_Test Account Cost for Goods Sold - _TC",
-			"_Test Bank - _TC", -existing_expense, "_Test Cost Center - _TC", submit=True, project="_Test Project", posting_date="2013-02-28")
+			"_Test Bank - _TC", -existing_expense, "_Test Cost Center - _TC", submit=True, project="_Test Project", posting_date=nowdate())
 
 def make_budget(**args):
 	args = frappe._dict(args)
@@ -269,10 +268,13 @@
 	budget_against=args.budget_against
 	cost_center=args.cost_center
 
+	fiscal_year = get_fiscal_year(nowdate())[0]
+
 	if budget_against == "Project":
-		budget_list = frappe.get_all("Budget", fields=["name"], filters = {"name": ("like", "_Test Project/_Test Fiscal Year 2013%")})
+		project_name = "{0}%".format("_Test Project/" + fiscal_year)
+		budget_list = frappe.get_all("Budget", fields=["name"], filters = {"name": ("like", project_name)})
 	else:
-		cost_center_name = "{0}%".format(cost_center or "_Test Cost Center - _TC/_Test Fiscal Year 2013")
+		cost_center_name = "{0}%".format(cost_center or "_Test Cost Center - _TC/" + fiscal_year)
 		budget_list = frappe.get_all("Budget", fields=["name"], filters = {"name": ("like", cost_center_name)})
 	for d in budget_list:
 		frappe.db.sql("delete from `tabBudget` where name = %(name)s", d)
@@ -285,8 +287,10 @@
 	else:
 		budget.cost_center =cost_center or "_Test Cost Center - _TC"
 
+	monthly_distribution = frappe.get_doc("Monthly Distribution", "_Test Distribution")
+	monthly_distribution.fiscal_year = fiscal_year
 
-	budget.fiscal_year = "_Test Fiscal Year 2013"
+	budget.fiscal_year = fiscal_year
 	budget.monthly_distribution = "_Test Distribution"
 	budget.company = "_Test Company"
 	budget.applicable_on_booking_actual_expenses = 1
@@ -295,7 +299,7 @@
 	budget.budget_against = budget_against
 	budget.append("accounts", {
 		"account": "_Test Account Cost for Goods Sold - _TC",
-		"budget_amount": 100000
+		"budget_amount": 200000
 	})
 
 	if args.applicable_on_material_request:
diff --git a/erpnext/accounts/doctype/cost_center/cost_center.js b/erpnext/accounts/doctype/cost_center/cost_center.js
index 96ec57d..9e2f6ee 100644
--- a/erpnext/accounts/doctype/cost_center/cost_center.js
+++ b/erpnext/accounts/doctype/cost_center/cost_center.js
@@ -18,7 +18,7 @@
 	},
 	refresh: function(frm) {
 		if (!frm.is_new()) {
-			frm.add_custom_button(__('Update Cost Center Number'), function () {
+			frm.add_custom_button(__('Update Cost Center Name / Number'), function () {
 				frm.trigger("update_cost_center_number");
 			});
 		}
@@ -47,35 +47,45 @@
 	},
 	update_cost_center_number: function(frm) {
 		var d = new frappe.ui.Dialog({
-			title: __('Update Cost Center Number'),
+			title: __('Update Cost Center Name / Number'),
 			fields: [
 				{
-					"label": 'Cost Center Number',
+					"label": "Cost Center Name",
+					"fieldname": "cost_center_name",
+					"fieldtype": "Data",
+					"reqd": 1,
+					"default": frm.doc.cost_center_name
+				},
+				{
+					"label": "Cost Center Number",
 					"fieldname": "cost_center_number",
 					"fieldtype": "Data",
-					"reqd": 1
+					"reqd": 1,
+					"default": frm.doc.cost_center_number
 				}
 			],
 			primary_action: function() {
 				var data = d.get_values();
-				if(data.cost_center_number === frm.doc.cost_center_number) {
+				if(data.cost_center_name === frm.doc.cost_center_name && data.cost_center_number === frm.doc.cost_center_number) {
 					d.hide();
 					return;
 				}
+				frappe.dom.freeze();
 				frappe.call({
-					method: "erpnext.accounts.utils.update_number_field",
+					method: "erpnext.accounts.utils.update_cost_center",
 					args: {
-						doctype_name: frm.doc.doctype,
-						name: frm.doc.name,
-						field_name: d.fields[0].fieldname,
-						number_value: data.cost_center_number,
+						docname: frm.doc.name,
+						cost_center_name: data.cost_center_name,
+						cost_center_number: data.cost_center_number,
 						company: frm.doc.company
 					},
 					callback: function(r) {
+						frappe.dom.unfreeze();
 						if(!r.exc) {
 							if(r.message) {
 								frappe.set_route("Form", "Cost Center", r.message);
 							} else {
+								me.frm.set_value("cost_center_name", data.cost_center_name);
 								me.frm.set_value("cost_center_number", data.cost_center_number);
 							}
 							d.hide();
diff --git a/erpnext/accounts/doctype/cost_center/cost_center.json b/erpnext/accounts/doctype/cost_center/cost_center.json
index 99b89d1..5013c92 100644
--- a/erpnext/accounts/doctype/cost_center/cost_center.json
+++ b/erpnext/accounts/doctype/cost_center/cost_center.json
@@ -2,7 +2,6 @@
  "actions": [],
  "allow_copy": 1,
  "allow_import": 1,
- "allow_rename": 1,
  "creation": "2013-01-23 19:57:17",
  "description": "Track separate Income and Expense for product verticals or divisions.",
  "doctype": "DocType",
@@ -126,7 +125,7 @@
  "idx": 1,
  "is_tree": 1,
  "links": [],
- "modified": "2020-03-18 17:59:04.321637",
+ "modified": "2020-04-29 16:09:30.025214",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "Cost Center",
diff --git a/erpnext/accounts/doctype/gl_entry/gl_entry.json b/erpnext/accounts/doctype/gl_entry/gl_entry.json
index 2214811..e6d97a1 100644
--- a/erpnext/accounts/doctype/gl_entry/gl_entry.json
+++ b/erpnext/accounts/doctype/gl_entry/gl_entry.json
@@ -1,4 +1,5 @@
 {
+ "actions": [],
  "autoname": "ACC-GLE-.YYYY.-.#####",
  "creation": "2013-01-10 16:34:06",
  "doctype": "DocType",
@@ -30,7 +31,8 @@
   "company",
   "finance_book",
   "to_rename",
-  "due_date"
+  "due_date",
+  "is_cancelled"
  ],
  "fields": [
   {
@@ -245,12 +247,18 @@
    "fieldname": "due_date",
    "fieldtype": "Date",
    "label": "Due Date"
+  },
+  {
+   "default": "0",
+   "fieldname": "is_cancelled",
+   "fieldtype": "Check",
+   "label": "Is Cancelled"
   }
  ],
  "icon": "fa fa-list",
  "idx": 1,
  "in_create": 1,
- "modified": "2020-03-28 16:22:33.766994",
+ "modified": "2020-04-07 16:22:33.766994",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "GL Entry",
diff --git a/erpnext/accounts/doctype/gl_entry/gl_entry.py b/erpnext/accounts/doctype/gl_entry/gl_entry.py
index 14d0531..efab580 100644
--- a/erpnext/accounts/doctype/gl_entry/gl_entry.py
+++ b/erpnext/accounts/doctype/gl_entry/gl_entry.py
@@ -30,23 +30,20 @@
 		self.pl_must_have_cost_center()
 		self.validate_cost_center()
 
-		if not self.flags.from_repost:
-			self.check_pl_account()
-			self.validate_party()
-			self.validate_currency()
+		self.check_pl_account()
+		self.validate_party()
+		self.validate_currency()
 
-	def on_update_with_args(self, adv_adj, update_outstanding = 'Yes', from_repost=False):
-		if not from_repost:
-			self.validate_account_details(adv_adj)
-			self.validate_dimensions_for_pl_and_bs()
-			check_freezing_date(self.posting_date, adv_adj)
+	def on_update_with_args(self, adv_adj, update_outstanding = 'Yes'):
+		self.validate_account_details(adv_adj)
+		self.validate_dimensions_for_pl_and_bs()
 
 		validate_frozen_account(self.account, adv_adj)
 		validate_balance_type(self.account, adv_adj)
 
 		# Update outstanding amt on against voucher
 		if self.against_voucher_type in ['Journal Entry', 'Sales Invoice', 'Purchase Invoice', 'Fees'] \
-			and self.against_voucher and update_outstanding == 'Yes' and not from_repost:
+			and self.against_voucher and update_outstanding == 'Yes':
 				update_outstanding_amt(self.account, self.party_type, self.party, self.against_voucher_type,
 					self.against_voucher)
 
@@ -159,7 +156,6 @@
 		if self.party_type and self.party:
 			validate_party_gle_currency(self.party_type, self.party, self.company, self.account_currency)
 
-
 	def validate_and_set_fiscal_year(self):
 		if not self.fiscal_year:
 			self.fiscal_year = get_fiscal_year(self.posting_date, company=self.company)[0]
@@ -176,19 +172,6 @@
 				(balance_must_be=="Credit" and flt(balance) > 0):
 				frappe.throw(_("Balance for Account {0} must always be {1}").format(account, _(balance_must_be)))
 
-def check_freezing_date(posting_date, adv_adj=False):
-	"""
-		Nobody can do GL Entries where posting date is before freezing date
-		except authorized person
-	"""
-	if not adv_adj:
-		acc_frozen_upto = frappe.db.get_value('Accounts Settings', None, 'acc_frozen_upto')
-		if acc_frozen_upto:
-			frozen_accounts_modifier = frappe.db.get_value( 'Accounts Settings', None,'frozen_accounts_modifier')
-			if getdate(posting_date) <= getdate(acc_frozen_upto) \
-					and not frozen_accounts_modifier in frappe.get_roles():
-				frappe.throw(_("You are not authorized to add or update entries before {0}").format(formatdate(acc_frozen_upto)))
-
 def update_outstanding_amt(account, party_type, party, against_voucher_type, against_voucher, on_cancel=False):
 	if party_type and party:
 		party_condition = " and party_type={0} and party={1}"\
diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.js b/erpnext/accounts/doctype/journal_entry/journal_entry.js
index 3604b60..9a832e3 100644
--- a/erpnext/accounts/doctype/journal_entry/journal_entry.js
+++ b/erpnext/accounts/doctype/journal_entry/journal_entry.js
@@ -12,7 +12,6 @@
 
 	refresh: function(frm) {
 		erpnext.toggle_naming_series();
-		frm.cscript.voucher_type(frm.doc);
 
 		if(frm.doc.docstatus==1) {
 			frm.add_custom_button(__('Ledger'), function() {
@@ -120,9 +119,78 @@
 				}
 			}
 		});
+	},
+
+	voucher_type: function(frm){
+
+		if(!frm.doc.company) return null;
+
+		if((!(frm.doc.accounts || []).length) || ((frm.doc.accounts || []).length === 1 && !frm.doc.accounts[0].account)) {
+			if(in_list(["Bank Entry", "Cash Entry"], frm.doc.voucher_type)) {
+				return frappe.call({
+					type: "GET",
+					method: "erpnext.accounts.doctype.journal_entry.journal_entry.get_default_bank_cash_account",
+					args: {
+						"account_type": (frm.doc.voucher_type=="Bank Entry" ?
+							"Bank" : (frm.doc.voucher_type=="Cash Entry" ? "Cash" : null)),
+						"company": frm.doc.company
+					},
+					callback: function(r) {
+						if(r.message) {
+							// If default company bank account not set
+							if(!$.isEmptyObject(r.message)){
+								update_jv_details(frm.doc, [r.message]);
+							}
+						}
+					}
+				});
+			}
+			else if(frm.doc.voucher_type=="Opening Entry") {
+				return frappe.call({
+					type:"GET",
+					method: "erpnext.accounts.doctype.journal_entry.journal_entry.get_opening_accounts",
+					args: {
+						"company": frm.doc.company
+					},
+					callback: function(r) {
+						frappe.model.clear_table(frm.doc, "accounts");
+						if(r.message) {
+							update_jv_details(frm.doc, r.message);
+						}
+						cur_frm.set_value("is_opening", "Yes");
+					}
+				});
+			}
+		}
+	},
+
+	from_template: function(frm){
+		if (frm.doc.from_template){
+			frappe.db.get_doc("Journal Entry Template", frm.doc.from_template)
+				.then((doc) => {
+					frappe.model.clear_table(frm.doc, "accounts");
+					frm.set_value({
+						"company": doc.company,
+						"voucher_type": doc.voucher_type,
+						"naming_series": doc.naming_series,
+						"is_opening": doc.is_opening,
+						"multi_currency": doc.multi_currency
+					})
+					update_jv_details(frm.doc, doc.accounts);
+				});
+		}
 	}
 });
 
+var update_jv_details = function(doc, r) {
+	$.each(r, function(i, d) {
+		var row = frappe.model.add_child(doc, "Journal Entry Account", "accounts");
+		row.account = d.account;
+		row.balance = d.balance;
+	});
+	refresh_field("accounts");
+}
+
 erpnext.accounts.JournalEntry = frappe.ui.form.Controller.extend({
 	onload: function() {
 		this.load_defaults();
@@ -375,56 +443,6 @@
 		cur_frm.pformat.print_heading = __("Journal Entry");
 }
 
-cur_frm.cscript.voucher_type = function(doc, cdt, cdn) {
-	cur_frm.set_df_property("cheque_no", "reqd", doc.voucher_type=="Bank Entry");
-	cur_frm.set_df_property("cheque_date", "reqd", doc.voucher_type=="Bank Entry");
-
-	if(!doc.company) return;
-
-	var update_jv_details = function(doc, r) {
-		$.each(r, function(i, d) {
-			var row = frappe.model.add_child(doc, "Journal Entry Account", "accounts");
-			row.account = d.account;
-			row.balance = d.balance;
-		});
-		refresh_field("accounts");
-	}
-
-	if((!(doc.accounts || []).length) || ((doc.accounts || []).length==1 && !doc.accounts[0].account)) {
-		if(in_list(["Bank Entry", "Cash Entry"], doc.voucher_type)) {
-			return frappe.call({
-				type: "GET",
-				method: "erpnext.accounts.doctype.journal_entry.journal_entry.get_default_bank_cash_account",
-				args: {
-					"account_type": (doc.voucher_type=="Bank Entry" ?
-						"Bank" : (doc.voucher_type=="Cash Entry" ? "Cash" : null)),
-					"company": doc.company
-				},
-				callback: function(r) {
-					if(r.message) {
-						update_jv_details(doc, [r.message]);
-					}
-				}
-			})
-		} else if(doc.voucher_type=="Opening Entry") {
-			return frappe.call({
-				type:"GET",
-				method: "erpnext.accounts.doctype.journal_entry.journal_entry.get_opening_accounts",
-				args: {
-					"company": doc.company
-				},
-				callback: function(r) {
-					frappe.model.clear_table(doc, "accounts");
-					if(r.message) {
-						update_jv_details(doc, r.message);
-					}
-					cur_frm.set_value("is_opening", "Yes")
-				}
-			})
-		}
-	}
-}
-
 frappe.ui.form.on("Journal Entry Account", {
 	party: function(frm, cdt, cdn) {
 		var d = frappe.get_doc(cdt, cdn);
diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.json b/erpnext/accounts/doctype/journal_entry/journal_entry.json
index f599124..9d50639 100644
--- a/erpnext/accounts/doctype/journal_entry/journal_entry.json
+++ b/erpnext/accounts/doctype/journal_entry/journal_entry.json
@@ -1,4 +1,5 @@
 {
+ "actions": [],
  "allow_import": 1,
  "autoname": "naming_series:",
  "creation": "2013-03-25 10:53:52",
@@ -10,10 +11,11 @@
   "title",
   "voucher_type",
   "naming_series",
-  "column_break1",
-  "posting_date",
-  "company",
   "finance_book",
+  "column_break1",
+  "from_template",
+  "company",
+  "posting_date",
   "2_add_edit_gl_entries",
   "accounts",
   "section_break99",
@@ -157,6 +159,7 @@
    "in_global_search": 1,
    "in_list_view": 1,
    "label": "Reference Number",
+   "mandatory_depends_on": "eval:doc.voucher_type == \"Bank Entry\"",
    "no_copy": 1,
    "oldfieldname": "cheque_no",
    "oldfieldtype": "Data",
@@ -166,6 +169,7 @@
    "fieldname": "cheque_date",
    "fieldtype": "Date",
    "label": "Reference Date",
+   "mandatory_depends_on": "eval:doc.voucher_type == \"Bank Entry\"",
    "no_copy": 1,
    "oldfieldname": "cheque_date",
    "oldfieldtype": "Date",
@@ -484,12 +488,22 @@
    "options": "Journal Entry",
    "print_hide": 1,
    "read_only": 1
+  },
+  {
+   "fieldname": "from_template",
+   "fieldtype": "Link",
+   "label": "From Template",
+   "no_copy": 1,
+   "options": "Journal Entry Template",
+   "print_hide": 1,
+   "report_hide": 1
   }
  ],
  "icon": "fa fa-file-text",
  "idx": 176,
  "is_submittable": 1,
- "modified": "2020-01-16 13:05:30.634226",
+ "links": [],
+ "modified": "2020-04-29 10:55:28.240916",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "Journal Entry",
diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py
index eb3017a..d6ffdb6 100644
--- a/erpnext/accounts/doctype/journal_entry/journal_entry.py
+++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py
@@ -57,6 +57,7 @@
 		from erpnext.hr.doctype.salary_slip.salary_slip import unlink_ref_doc_from_salary_slip
 		unlink_ref_doc_from_payment_entries(self)
 		unlink_ref_doc_from_salary_slip(self.name)
+		self.ignore_linked_doctypes = ('GL Entry', 'Stock Ledger Entry')
 		self.make_gl_entries(1)
 		self.update_advance_paid()
 		self.update_expense_claim()
@@ -594,7 +595,7 @@
 		for d in self.accounts:
 			if d.reference_type=="Expense Claim" and d.reference_name:
 				doc = frappe.get_doc("Expense Claim", d.reference_name)
-				update_reimbursed_amount(doc)
+				update_reimbursed_amount(doc, jv=self.name)
 
 
 	def validate_expense_claim(self):
diff --git a/erpnext/accounts/doctype/journal_entry_account/journal_entry_account.json b/erpnext/accounts/doctype/journal_entry_account/journal_entry_account.json
index 9552e60..26c84a6 100644
--- a/erpnext/accounts/doctype/journal_entry_account/journal_entry_account.json
+++ b/erpnext/accounts/doctype/journal_entry_account/journal_entry_account.json
@@ -1,4 +1,5 @@
 {
+ "actions": [],
  "autoname": "hash",
  "creation": "2013-02-22 01:27:39",
  "doctype": "DocType",
@@ -271,7 +272,8 @@
  ],
  "idx": 1,
  "istable": 1,
- "modified": "2020-01-13 12:41:33.968025",
+ "links": [],
+ "modified": "2020-04-25 01:47:49.060128",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "Journal Entry Account",
@@ -280,4 +282,4 @@
  "sort_field": "modified",
  "sort_order": "DESC",
  "track_changes": 1
-}
+}
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/account_subtype/__init__.py b/erpnext/accounts/doctype/journal_entry_template/__init__.py
similarity index 100%
copy from erpnext/accounts/doctype/account_subtype/__init__.py
copy to erpnext/accounts/doctype/journal_entry_template/__init__.py
diff --git a/erpnext/accounts/doctype/journal_entry_template/journal_entry_template.js b/erpnext/accounts/doctype/journal_entry_template/journal_entry_template.js
new file mode 100644
index 0000000..cbb9fc4
--- /dev/null
+++ b/erpnext/accounts/doctype/journal_entry_template/journal_entry_template.js
@@ -0,0 +1,91 @@
+// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+frappe.ui.form.on("Journal Entry Template", {
+	setup: function(frm) {
+		frappe.model.set_default_values(frm.doc);
+
+		frm.set_query("account" ,"accounts", function(){
+			var filters = {
+				company: frm.doc.company,
+				is_group: 0
+			};
+
+			if(!frm.doc.multi_currency) {
+				$.extend(filters, {
+					account_currency: frappe.get_doc(":Company", frm.doc.company).default_currency
+				});
+			}
+
+			return { filters: filters };
+		});
+
+		frappe.call({
+			type: "GET",
+			method: "erpnext.accounts.doctype.journal_entry_template.journal_entry_template.get_naming_series",
+			callback: function(r){
+				if(r.message){
+					frm.set_df_property("naming_series", "options", r.message.split("\n"));
+					frm.set_value("naming_series", r.message.split("\n")[0]);
+					frm.refresh_field("naming_series");
+				}
+			}
+		});
+	},
+	voucher_type: function(frm) {
+		var add_accounts = function(doc, r) {
+			$.each(r, function(i, d) {
+				var row = frappe.model.add_child(doc, "Journal Entry Template Account", "accounts");
+				row.account = d.account;
+			});
+			refresh_field("accounts");
+		};
+
+		if(!frm.doc.company) return;
+
+		frm.trigger("clear_child");
+		switch(frm.doc.voucher_type){
+			case "Opening Entry":
+				frm.set_value("is_opening", "Yes");
+				frappe.call({
+					type:"GET",
+					method: "erpnext.accounts.doctype.journal_entry.journal_entry.get_opening_accounts",
+					args: {
+						"company": frm.doc.company
+					},
+					callback: function(r) {
+						if(r.message) {
+							add_accounts(frm.doc, r.message);
+						}
+					}
+				});
+				break;
+			case "Bank Entry":
+			case "Cash Entry":
+				frappe.call({
+					type: "GET",
+					method: "erpnext.accounts.doctype.journal_entry.journal_entry.get_default_bank_cash_account",
+					args: {
+						"account_type": (frm.doc.voucher_type=="Bank Entry" ?
+							"Bank" : (frm.doc.voucher_type=="Cash Entry" ? "Cash" : null)),
+						"company": frm.doc.company
+					},
+					callback: function(r) {
+						if(r.message) {
+							// If default company bank account not set
+							if(!$.isEmptyObject(r.message)){
+								add_accounts(frm.doc, [r.message]);
+							}
+						}
+					}
+				});
+				break;
+			default:
+				frm.trigger("clear_child");
+		}
+	},
+	clear_child: function(frm){
+		frappe.model.clear_table(frm.doc, "accounts");
+		frm.refresh_field("accounts");
+	}
+});
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/journal_entry_template/journal_entry_template.json b/erpnext/accounts/doctype/journal_entry_template/journal_entry_template.json
new file mode 100644
index 0000000..660ae85
--- /dev/null
+++ b/erpnext/accounts/doctype/journal_entry_template/journal_entry_template.json
@@ -0,0 +1,134 @@
+{
+ "actions": [],
+ "autoname": "field:template_title",
+ "creation": "2020-04-09 01:32:51.332301",
+ "doctype": "DocType",
+ "document_type": "Document",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "section_break_1",
+  "template_title",
+  "voucher_type",
+  "naming_series",
+  "column_break_3",
+  "company",
+  "is_opening",
+  "multi_currency",
+  "section_break_3",
+  "accounts"
+ ],
+ "fields": [
+  {
+   "fieldname": "section_break_1",
+   "fieldtype": "Section Break"
+  },
+  {
+   "fieldname": "voucher_type",
+   "fieldtype": "Select",
+   "in_list_view": 1,
+   "label": "Journal Entry Type",
+   "options": "Journal Entry\nInter Company Journal Entry\nBank Entry\nCash Entry\nCredit Card Entry\nDebit Note\nCredit Note\nContra Entry\nExcise Entry\nWrite Off Entry\nOpening Entry\nDepreciation Entry\nExchange Rate Revaluation",
+   "reqd": 1
+  },
+  {
+   "fieldname": "company",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "in_standard_filter": 1,
+   "label": "Company",
+   "options": "Company",
+   "remember_last_selected_value": 1,
+   "reqd": 1
+  },
+  {
+   "fieldname": "column_break_3",
+   "fieldtype": "Column Break"
+  },
+  {
+   "default": "No",
+   "fieldname": "is_opening",
+   "fieldtype": "Select",
+   "label": "Is Opening",
+   "options": "No\nYes"
+  },
+  {
+   "fieldname": "accounts",
+   "fieldtype": "Table",
+   "label": "Accounting Entries",
+   "options": "Journal Entry Template Account"
+  },
+  {
+   "fieldname": "naming_series",
+   "fieldtype": "Select",
+   "label": "Series",
+   "no_copy": 1,
+   "print_hide": 1,
+   "reqd": 1,
+   "set_only_once": 1
+  },
+  {
+   "fieldname": "template_title",
+   "fieldtype": "Data",
+   "label": "Template Title",
+   "reqd": 1,
+   "unique": 1
+  },
+  {
+   "fieldname": "section_break_3",
+   "fieldtype": "Section Break"
+  },
+  {
+   "default": "0",
+   "fieldname": "multi_currency",
+   "fieldtype": "Check",
+   "label": "Multi Currency"
+  }
+ ],
+ "links": [],
+ "modified": "2020-05-01 18:32:01.420488",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "Journal Entry Template",
+ "owner": "Administrator",
+ "permissions": [
+  {
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "export": 1,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "Accounts User",
+   "share": 1,
+   "write": 1
+  },
+  {
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "export": 1,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "Accounts Manager",
+   "share": 1,
+   "write": 1
+  },
+  {
+   "email": 1,
+   "export": 1,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "Auditor",
+   "share": 1
+  }
+ ],
+ "search_fields": "voucher_type, company",
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "title_field": "template_title",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/journal_entry_template/journal_entry_template.py b/erpnext/accounts/doctype/journal_entry_template/journal_entry_template.py
new file mode 100644
index 0000000..e0b9cbc
--- /dev/null
+++ b/erpnext/accounts/doctype/journal_entry_template/journal_entry_template.py
@@ -0,0 +1,14 @@
+# -*- 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 JournalEntryTemplate(Document):
+	pass
+
+@frappe.whitelist()
+def get_naming_series():
+	return frappe.get_meta("Journal Entry").get_field("naming_series").options
diff --git a/erpnext/accounts/doctype/journal_entry_template/test_journal_entry_template.py b/erpnext/accounts/doctype/journal_entry_template/test_journal_entry_template.py
new file mode 100644
index 0000000..5f74a20
--- /dev/null
+++ b/erpnext/accounts/doctype/journal_entry_template/test_journal_entry_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 TestJournalEntryTemplate(unittest.TestCase):
+	pass
diff --git a/erpnext/accounts/doctype/account_subtype/__init__.py b/erpnext/accounts/doctype/journal_entry_template_account/__init__.py
similarity index 100%
copy from erpnext/accounts/doctype/account_subtype/__init__.py
copy to erpnext/accounts/doctype/journal_entry_template_account/__init__.py
diff --git a/erpnext/accounts/doctype/journal_entry_template_account/journal_entry_template_account.json b/erpnext/accounts/doctype/journal_entry_template_account/journal_entry_template_account.json
new file mode 100644
index 0000000..eecd877
--- /dev/null
+++ b/erpnext/accounts/doctype/journal_entry_template_account/journal_entry_template_account.json
@@ -0,0 +1,31 @@
+{
+ "actions": [],
+ "creation": "2020-04-09 01:48:42.783620",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "account"
+ ],
+ "fields": [
+  {
+   "fieldname": "account",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "label": "Account",
+   "options": "Account",
+   "reqd": 1
+  }
+ ],
+ "istable": 1,
+ "links": [],
+ "modified": "2020-04-25 01:15:44.879839",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "Journal Entry Template Account",
+ "owner": "Administrator",
+ "permissions": [],
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/journal_entry_template_account/journal_entry_template_account.py b/erpnext/accounts/doctype/journal_entry_template_account/journal_entry_template_account.py
new file mode 100644
index 0000000..48e6abb
--- /dev/null
+++ b/erpnext/accounts/doctype/journal_entry_template_account/journal_entry_template_account.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 JournalEntryTemplateAccount(Document):
+	pass
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.js b/erpnext/accounts/doctype/payment_entry/payment_entry.js
index b7c97a7..a378a51 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.js
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.js
@@ -106,6 +106,21 @@
 			};
 		});
 
+		frm.set_query('payment_term', 'references', function(frm, cdt, cdn) {
+			const child = locals[cdt][cdn];
+			if (in_list(['Purchase Invoice', 'Sales Invoice'], child.reference_doctype) && child.reference_name) {
+				let payment_term_list = frappe.get_list('Payment Schedule', {'parent': child.reference_name});
+
+				payment_term_list = payment_term_list.map(pt => pt.payment_term);
+
+				return {
+					filters: {
+						'name': ['in', payment_term_list]
+					}
+				}
+			}
+		});
+
 		frm.set_query("reference_name", "references", function(doc, cdt, cdn) {
 			const child = locals[cdt][cdn];
 			const filters = {"docstatus": 1, "company": doc.company};
@@ -287,7 +302,7 @@
 			frm.set_value("contact_email", "");
 			frm.set_value("contact_person", "");
 		}
-		if(frm.doc.payment_type && frm.doc.party_type && frm.doc.party) {
+		if(frm.doc.payment_type && frm.doc.party_type && frm.doc.party && frm.doc.company) {
 			if(!frm.doc.posting_date) {
 				frappe.msgprint(__("Please select Posting Date before selecting Party"))
 				frm.set_value("party", "");
@@ -1033,4 +1048,4 @@
 			});
 		}
 	},
-})
+})
\ 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 a453e95..bcb22f0 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.py
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py
@@ -60,6 +60,7 @@
 		self.set_remarks()
 		self.validate_duplicate_entry()
 		self.validate_allocated_amount()
+		self.validate_paid_invoices()
 		self.ensure_supplier_is_not_blocked()
 		self.set_status()
 
@@ -71,16 +72,18 @@
 		self.update_outstanding_amounts()
 		self.update_advance_paid()
 		self.update_expense_claim()
+		self.update_payment_schedule()
 		self.set_status()
 
-
 	def on_cancel(self):
+		self.ignore_linked_doctypes = ('GL Entry', 'Stock Ledger Entry')
 		self.setup_party_account_field()
 		self.make_gl_entries(cancel=1)
 		self.update_outstanding_amounts()
 		self.update_advance_paid()
 		self.update_expense_claim()
 		self.delink_advance_entry_references()
+		self.update_payment_schedule(cancel=1)
 		self.set_payment_req_status()
 		self.set_status()
 	
@@ -94,10 +97,10 @@
 	def validate_duplicate_entry(self):
 		reference_names = []
 		for d in self.get("references"):
-			if (d.reference_doctype, d.reference_name) in reference_names:
+			if (d.reference_doctype, d.reference_name, d.payment_term) in reference_names:
 				frappe.throw(_("Row #{0}: Duplicate entry in References {1} {2}")
 					.format(d.idx, d.reference_doctype, d.reference_name))
-			reference_names.append((d.reference_doctype, d.reference_name))
+			reference_names.append((d.reference_doctype, d.reference_name, d.payment_term))
 
 	def set_bank_account_data(self):
 		if self.bank_account:
@@ -264,6 +267,25 @@
 						frappe.throw(_("{0} {1} must be submitted")
 							.format(d.reference_doctype, d.reference_name))
 
+	def validate_paid_invoices(self):
+		no_oustanding_refs = {}
+
+		for d in self.get("references"):
+			if not d.allocated_amount:
+				continue
+
+			if d.reference_doctype in ("Sales Invoice", "Purchase Invoice", "Fees"):
+				outstanding_amount, is_return = frappe.get_cached_value(d.reference_doctype, d.reference_name, ["outstanding_amount", "is_return"])
+				if outstanding_amount <= 0 and not is_return:
+					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")),
+				title=_("Warning"), indicator="orange")
+
+
 	def validate_journal_entry(self):
 		for d in self.get("references"):
 			if d.allocated_amount and d.reference_doctype == "Journal Entry":
@@ -285,6 +307,36 @@
 						frappe.throw(_("Against Journal Entry {0} does not have any unmatched {1} entry")
 							.format(d.reference_name, dr_or_cr))
 
+	def update_payment_schedule(self, cancel=0):
+		invoice_payment_amount_map = {}
+		invoice_paid_amount_map = {}
+
+		for reference in self.get('references'):
+			if reference.payment_term and reference.reference_name:
+				key = (reference.payment_term, reference.reference_name)
+				invoice_payment_amount_map.setdefault(key, 0.0)
+				invoice_payment_amount_map[key] += reference.allocated_amount
+
+				if not invoice_paid_amount_map.get(reference.reference_name):
+					payment_schedule = frappe.get_all('Payment Schedule', filters={'parent': reference.reference_name},
+						fields=['paid_amount', 'payment_amount', 'payment_term'])
+					for term in payment_schedule:
+						invoice_key = (term.payment_term, reference.reference_name)
+						invoice_paid_amount_map.setdefault(invoice_key, {})
+						invoice_paid_amount_map[invoice_key]['outstanding'] = term.payment_amount - term.paid_amount
+
+		for key, amount in iteritems(invoice_payment_amount_map):
+			if cancel:
+				frappe.db.sql(""" UPDATE `tabPayment Schedule` SET paid_amount = `paid_amount` - %s
+					WHERE parent = %s and payment_term = %s""", (amount, key[1], key[0]))
+			else:
+				outstanding = invoice_paid_amount_map.get(key)['outstanding']
+				if amount > outstanding:
+					frappe.throw(_('Cannot allocate more than {0} against payment term {1}').format(outstanding, key[0]))
+
+				frappe.db.sql(""" UPDATE `tabPayment Schedule` SET paid_amount = `paid_amount` + %s
+						WHERE parent = %s and payment_term = %s""", (amount, key[1], key[0]))
+
 	def set_status(self):
 		if self.docstatus == 2:
 			self.status = 'Cancelled'
@@ -540,7 +592,7 @@
 			for d in self.get("references"):
 				if d.reference_doctype=="Expense Claim" and d.reference_name:
 					doc = frappe.get_doc("Expense Claim", d.reference_name)
-					update_reimbursed_amount(doc)
+					update_reimbursed_amount(doc, self.name)
 
 	def on_recurring(self, reference_doc, auto_repeat_doc):
 		self.reference_no = reference_doc.name
@@ -1012,15 +1064,22 @@
 	if doc.doctype == "Purchase Invoice" and doc.invoice_is_blocked():
 		frappe.msgprint(_('{0} is on hold till {1}').format(doc.name, doc.release_date))
 	else:
-		pe.append("references", {
-			'reference_doctype': dt,
-			'reference_name': dn,
-			"bill_no": doc.get("bill_no"),
-			"due_date": doc.get("due_date"),
-			'total_amount': grand_total,
-			'outstanding_amount': outstanding_amount,
-			'allocated_amount': outstanding_amount
-		})
+		if (doc.doctype in ('Sales Invoice', 'Purchase Invoice')
+			and frappe.get_value('Payment Terms Template',
+			{'name': doc.payment_terms_template}, 'allocate_payment_based_on_payment_terms')):
+
+			for reference in get_reference_as_per_payment_terms(doc.payment_schedule, dt, dn, doc, grand_total, outstanding_amount):
+				pe.append('references', reference)
+		else:
+			pe.append("references", {
+				'reference_doctype': dt,
+				'reference_name': dn,
+				"bill_no": doc.get("bill_no"),
+				"due_date": doc.get("due_date"),
+				'total_amount': grand_total,
+				'outstanding_amount': outstanding_amount,
+				'allocated_amount': outstanding_amount
+			})
 
 	pe.setup_party_account_field()
 	pe.set_missing_values()
@@ -1029,6 +1088,22 @@
 		pe.set_amounts()
 	return pe
 
+def get_reference_as_per_payment_terms(payment_schedule, dt, dn, doc, grand_total, outstanding_amount):
+	references = []
+	for payment_term in payment_schedule:
+		references.append({
+			'reference_doctype': dt,
+			'reference_name': dn,
+			'bill_no': doc.get('bill_no'),
+			'due_date': doc.get('due_date'),
+			'total_amount': grand_total,
+			'outstanding_amount': outstanding_amount,
+			'payment_term': payment_term.payment_term,
+			'allocated_amount': flt(payment_term.payment_amount - payment_term.paid_amount,
+				payment_term.precision('payment_amount'))
+		})
+
+	return references
 
 def get_paid_amount(dt, dn, party_type, party, account, due_date):
 	if party_type=="Customer":
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry_list.js b/erpnext/accounts/doctype/payment_entry/payment_entry_list.js
new file mode 100644
index 0000000..7ea60bb
--- /dev/null
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry_list.js
@@ -0,0 +1,12 @@
+frappe.listview_settings['Payment Entry'] = {
+
+	onload: function(listview) {
+		listview.page.fields_dict.party_type.get_query = function() {
+			return {
+				"filters": {
+					"name": ["in", Object.keys(frappe.boot.party_account_types)],
+				}
+			};
+		};
+	}
+};
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/payment_entry/test_payment_entry.py b/erpnext/accounts/doctype/payment_entry/test_payment_entry.py
index a25e0e3..8bb741f 100644
--- a/erpnext/accounts/doctype/payment_entry/test_payment_entry.py
+++ b/erpnext/accounts/doctype/payment_entry/test_payment_entry.py
@@ -35,8 +35,6 @@
 
 		pe.cancel()
 
-		self.assertFalse(self.get_gle(pe.name))
-
 		so_advance_paid = frappe.db.get_value("Sales Order", so.name, "advance_paid")
 		self.assertEqual(so_advance_paid, 0)
 
@@ -124,7 +122,6 @@
 		self.assertEqual(outstanding_amount, 0)
 
 		pe.cancel()
-		self.assertFalse(self.get_gle(pe.name))
 
 		outstanding_amount = flt(frappe.db.get_value("Sales Invoice", si.name, "outstanding_amount"))
 		self.assertEqual(outstanding_amount, 100)
@@ -171,6 +168,32 @@
 		self.assertEqual(flt(outstanding_amount), 100)
 		self.assertEqual(status, 'Unpaid')
 
+	def test_payment_entry_against_payment_terms(self):
+		si = create_sales_invoice(do_not_save=1, qty=1, rate=200)
+		create_payment_terms_template()
+		si.payment_terms_template = 'Test Receivable Template'
+
+		si.append('taxes', {
+			"charge_type": "On Net Total",
+			"account_head": "_Test Account Service Tax - _TC",
+			"cost_center": "_Test Cost Center - _TC",
+			"description": "Service Tax",
+			"rate": 18
+		})
+		si.save()
+
+		si.submit()
+
+		pe = get_payment_entry("Sales Invoice", si.name, bank_account="_Test Cash - _TC")
+		pe.submit()
+		si.load_from_db()
+
+		self.assertEqual(pe.references[0].payment_term, 'Basic Amount Receivable')
+		self.assertEqual(pe.references[1].payment_term, 'Tax Receivable')
+		self.assertEqual(si.payment_schedule[0].paid_amount, 200.0)
+		self.assertEqual(si.payment_schedule[1].paid_amount, 36.0)
+
+
 	def test_payment_against_purchase_invoice_to_check_status(self):
 		pi = make_purchase_invoice(supplier="_Test Supplier USD", debit_to="_Test Payable USD - _TC",
 			currency="USD", conversion_rate=50)
@@ -355,7 +378,6 @@
 		self.assertEqual(outstanding_amount, 0)
 
 		pe3.cancel()
-		self.assertFalse(self.get_gle(pe3.name))
 
 		outstanding_amount = flt(frappe.db.get_value("Sales Invoice", si1.name, "outstanding_amount"))
 		self.assertEqual(outstanding_amount, -100)
@@ -609,4 +631,38 @@
 		self.assertEqual(expected_party_account_balance, party_account_balance)
 
 		accounts_settings.allow_cost_center_in_entry_of_bs_account = 0
-		accounts_settings.save()
\ No newline at end of file
+		accounts_settings.save()
+
+def create_payment_terms_template():
+
+	create_payment_term('Basic Amount Receivable')
+	create_payment_term('Tax Receivable')
+
+	if not frappe.db.exists('Payment Terms Template', 'Test Receivable Template'):
+		payment_term_template = frappe.get_doc({
+			'doctype': 'Payment Terms Template',
+			'template_name': 'Test Receivable Template',
+			'allocate_payment_based_on_payment_terms': 1,
+			'terms': [{
+				'doctype': 'Payment Terms Template Detail',
+				'payment_term': 'Basic Amount Receivable',
+				'invoice_portion': 84.746,
+				'credit_days_based_on': 'Day(s) after invoice date',
+				'credit_days': 1
+			},
+			{
+				'doctype': 'Payment Terms Template Detail',
+				'payment_term': 'Tax Receivable',
+				'invoice_portion': 15.254,
+				'credit_days_based_on': 'Day(s) after invoice date',
+				'credit_days': 2
+			}]
+		}).insert()
+
+
+def create_payment_term(name):
+	if not frappe.db.exists('Payment Term', name):
+		frappe.get_doc({
+			'doctype': 'Payment Term',
+			'payment_term_name': name
+		}).insert()
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/payment_entry_reference/payment_entry_reference.json b/erpnext/accounts/doctype/payment_entry_reference/payment_entry_reference.json
index b6a6643..8f5e9fb 100644
--- a/erpnext/accounts/doctype/payment_entry_reference/payment_entry_reference.json
+++ b/erpnext/accounts/doctype/payment_entry_reference/payment_entry_reference.json
@@ -1,343 +1,107 @@
 {
- "allow_copy": 0,
- "allow_events_in_timeline": 0,
- "allow_guest_to_view": 0,
- "allow_import": 0,
- "allow_rename": 0,
- "beta": 0,
+ "actions": [],
  "creation": "2016-06-01 16:55:32.196722",
- "custom": 0,
- "docstatus": 0,
  "doctype": "DocType",
- "document_type": "",
  "editable_grid": 1,
  "engine": "InnoDB",
+ "field_order": [
+  "reference_doctype",
+  "reference_name",
+  "due_date",
+  "bill_no",
+  "payment_term",
+  "column_break_4",
+  "total_amount",
+  "outstanding_amount",
+  "allocated_amount",
+  "exchange_rate"
+ ],
  "fields": [
   {
-   "allow_bulk_edit": 0,
-   "allow_in_quick_entry": 0,
-   "allow_on_submit": 0,
-   "bold": 0,
-   "collapsible": 0,
    "columns": 2,
-   "fetch_if_empty": 0,
    "fieldname": "reference_doctype",
    "fieldtype": "Link",
-   "hidden": 0,
-   "ignore_user_permissions": 0,
-   "ignore_xss_filter": 0,
-   "in_filter": 0,
-   "in_global_search": 0,
    "in_list_view": 1,
-   "in_standard_filter": 0,
    "label": "Type",
-   "length": 0,
-   "no_copy": 0,
    "options": "DocType",
-   "permlevel": 0,
-   "precision": "",
-   "print_hide": 0,
-   "print_hide_if_no_value": 0,
-   "read_only": 0,
-   "remember_last_selected_value": 0,
-   "report_hide": 0,
-   "reqd": 1,
-   "search_index": 0,
-   "set_only_once": 0,
-   "translatable": 0,
-   "unique": 0
+   "reqd": 1
   },
   {
-   "allow_bulk_edit": 0,
-   "allow_in_quick_entry": 0,
-   "allow_on_submit": 0,
-   "bold": 0,
-   "collapsible": 0,
    "columns": 2,
-   "fetch_if_empty": 0,
    "fieldname": "reference_name",
    "fieldtype": "Dynamic Link",
-   "hidden": 0,
-   "ignore_user_permissions": 0,
-   "ignore_xss_filter": 0,
-   "in_filter": 0,
    "in_global_search": 1,
    "in_list_view": 1,
-   "in_standard_filter": 0,
    "label": "Name",
-   "length": 0,
-   "no_copy": 0,
    "options": "reference_doctype",
-   "permlevel": 0,
-   "precision": "",
-   "print_hide": 0,
-   "print_hide_if_no_value": 0,
-   "read_only": 0,
-   "remember_last_selected_value": 0,
-   "report_hide": 0,
-   "reqd": 1,
-   "search_index": 0,
-   "set_only_once": 0,
-   "translatable": 0,
-   "unique": 0
+   "reqd": 1
   },
   {
-   "allow_bulk_edit": 0,
-   "allow_in_quick_entry": 0,
-   "allow_on_submit": 0,
-   "bold": 0,
-   "collapsible": 0,
-   "columns": 0,
-   "fetch_if_empty": 0,
    "fieldname": "due_date",
    "fieldtype": "Date",
-   "hidden": 0,
-   "ignore_user_permissions": 0,
-   "ignore_xss_filter": 0,
-   "in_filter": 0,
-   "in_global_search": 0,
-   "in_list_view": 0,
-   "in_standard_filter": 0,
    "label": "Due Date",
-   "length": 0,
-   "no_copy": 0,
-   "permlevel": 0,
-   "precision": "",
-   "print_hide": 0,
-   "print_hide_if_no_value": 0,
-   "read_only": 1,
-   "remember_last_selected_value": 0,
-   "report_hide": 0,
-   "reqd": 0,
-   "search_index": 0,
-   "set_only_once": 0,
-   "translatable": 0,
-   "unique": 0
+   "read_only": 1
   },
   {
-   "allow_bulk_edit": 0,
-   "allow_in_quick_entry": 0,
-   "allow_on_submit": 0,
-   "bold": 0,
-   "collapsible": 0,
-   "columns": 0,
-   "depends_on": "",
-   "fetch_if_empty": 0,
    "fieldname": "bill_no",
    "fieldtype": "Data",
-   "hidden": 0,
-   "ignore_user_permissions": 0,
-   "ignore_xss_filter": 0,
-   "in_filter": 0,
-   "in_global_search": 0,
-   "in_list_view": 0,
-   "in_standard_filter": 0,
    "label": "Supplier Invoice No",
-   "length": 0,
    "no_copy": 1,
-   "permlevel": 0,
-   "precision": "",
-   "print_hide": 0,
-   "print_hide_if_no_value": 0,
-   "read_only": 1,
-   "remember_last_selected_value": 0,
-   "report_hide": 0,
-   "reqd": 0,
-   "search_index": 0,
-   "set_only_once": 0,
-   "translatable": 0,
-   "unique": 0
+   "read_only": 1
   },
   {
-   "allow_bulk_edit": 0,
-   "allow_in_quick_entry": 0,
-   "allow_on_submit": 0,
-   "bold": 0,
-   "collapsible": 0,
-   "columns": 0,
-   "fetch_if_empty": 0,
    "fieldname": "column_break_4",
-   "fieldtype": "Column Break",
-   "hidden": 0,
-   "ignore_user_permissions": 0,
-   "ignore_xss_filter": 0,
-   "in_filter": 0,
-   "in_global_search": 0,
-   "in_list_view": 0,
-   "in_standard_filter": 0,
-   "length": 0,
-   "no_copy": 0,
-   "permlevel": 0,
-   "precision": "",
-   "print_hide": 0,
-   "print_hide_if_no_value": 0,
-   "read_only": 0,
-   "remember_last_selected_value": 0,
-   "report_hide": 0,
-   "reqd": 0,
-   "search_index": 0,
-   "set_only_once": 0,
-   "translatable": 0,
-   "unique": 0
+   "fieldtype": "Column Break"
   },
   {
-   "allow_bulk_edit": 0,
-   "allow_in_quick_entry": 0,
-   "allow_on_submit": 0,
-   "bold": 0,
-   "collapsible": 0,
    "columns": 2,
-   "fetch_if_empty": 0,
    "fieldname": "total_amount",
    "fieldtype": "Float",
-   "hidden": 0,
-   "ignore_user_permissions": 0,
-   "ignore_xss_filter": 0,
-   "in_filter": 0,
-   "in_global_search": 0,
    "in_list_view": 1,
-   "in_standard_filter": 0,
    "label": "Total Amount",
-   "length": 0,
-   "no_copy": 0,
-   "permlevel": 0,
-   "precision": "",
    "print_hide": 1,
-   "print_hide_if_no_value": 0,
-   "read_only": 1,
-   "remember_last_selected_value": 0,
-   "report_hide": 0,
-   "reqd": 0,
-   "search_index": 0,
-   "set_only_once": 0,
-   "translatable": 0,
-   "unique": 0
+   "read_only": 1
   },
   {
-   "allow_bulk_edit": 0,
-   "allow_in_quick_entry": 0,
-   "allow_on_submit": 0,
-   "bold": 0,
-   "collapsible": 0,
    "columns": 2,
-   "fetch_if_empty": 0,
    "fieldname": "outstanding_amount",
    "fieldtype": "Float",
-   "hidden": 0,
-   "ignore_user_permissions": 0,
-   "ignore_xss_filter": 0,
-   "in_filter": 0,
-   "in_global_search": 0,
    "in_list_view": 1,
-   "in_standard_filter": 0,
    "label": "Outstanding",
-   "length": 0,
-   "no_copy": 0,
-   "permlevel": 0,
-   "precision": "",
-   "print_hide": 0,
-   "print_hide_if_no_value": 0,
-   "read_only": 1,
-   "remember_last_selected_value": 0,
-   "report_hide": 0,
-   "reqd": 0,
-   "search_index": 0,
-   "set_only_once": 0,
-   "translatable": 0,
-   "unique": 0
+   "read_only": 1
   },
   {
-   "allow_bulk_edit": 0,
-   "allow_in_quick_entry": 0,
-   "allow_on_submit": 0,
-   "bold": 0,
-   "collapsible": 0,
    "columns": 2,
-   "fetch_if_empty": 0,
    "fieldname": "allocated_amount",
    "fieldtype": "Float",
-   "hidden": 0,
-   "ignore_user_permissions": 0,
-   "ignore_xss_filter": 0,
-   "in_filter": 0,
-   "in_global_search": 0,
    "in_list_view": 1,
-   "in_standard_filter": 0,
-   "label": "Allocated",
-   "length": 0,
-   "no_copy": 0,
-   "permlevel": 0,
-   "precision": "",
-   "print_hide": 0,
-   "print_hide_if_no_value": 0,
-   "read_only": 0,
-   "remember_last_selected_value": 0,
-   "report_hide": 0,
-   "reqd": 0,
-   "search_index": 0,
-   "set_only_once": 0,
-   "translatable": 0,
-   "unique": 0
+   "label": "Allocated"
   },
   {
-   "allow_bulk_edit": 0,
-   "allow_in_quick_entry": 0,
-   "allow_on_submit": 0,
-   "bold": 0,
-   "collapsible": 0,
-   "columns": 0,
    "depends_on": "eval:(doc.reference_doctype=='Purchase Invoice')",
-   "fetch_if_empty": 0,
    "fieldname": "exchange_rate",
    "fieldtype": "Float",
-   "hidden": 0,
-   "ignore_user_permissions": 0,
-   "ignore_xss_filter": 0,
-   "in_filter": 0,
-   "in_global_search": 0,
-   "in_list_view": 0,
-   "in_standard_filter": 0,
    "label": "Exchange Rate",
-   "length": 0,
-   "no_copy": 0,
-   "permlevel": 0,
-   "precision": "",
    "print_hide": 1,
-   "print_hide_if_no_value": 0,
-   "read_only": 1,
-   "remember_last_selected_value": 0,
-   "report_hide": 0,
-   "reqd": 0,
-   "search_index": 0,
-   "set_only_once": 0,
-   "translatable": 0,
-   "unique": 0
+   "read_only": 1
+  },
+  {
+   "fieldname": "payment_term",
+   "fieldtype": "Link",
+   "label": "Payment Term",
+   "options": "Payment Term"
   }
  ],
- "has_web_view": 0,
- "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": "2019-05-01 13:24:56.586677",
+ "links": [],
+ "modified": "2020-03-13 12:07:19.362539",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "Payment Entry Reference",
- "name_case": "",
  "owner": "Administrator",
  "permissions": [],
  "quick_entry": 1,
- "read_only": 0,
- "read_only_onload": 0,
- "show_name_in_global_search": 0,
  "sort_field": "modified",
  "sort_order": "DESC",
- "track_changes": 1,
- "track_seen": 0,
- "track_views": 0
+ "track_changes": 1
 }
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/payment_request/payment_request.py b/erpnext/accounts/doctype/payment_request/payment_request.py
index 53ff222..68aeb6d 100644
--- a/erpnext/accounts/doctype/payment_request/payment_request.py
+++ b/erpnext/accounts/doctype/payment_request/payment_request.py
@@ -326,7 +326,7 @@
 			"reference_doctype": args.dt,
 			"reference_name": args.dn,
 			"party_type": args.get("party_type") or "Customer",
-			"party": args.get("party") or ref_doc.customer,
+			"party": args.get("party") or ref_doc.get("customer"),
 			"bank_account": bank_account
 		})
 
@@ -420,7 +420,7 @@
 
 def update_payment_req_status(doc, method):
 	from erpnext.accounts.doctype.payment_entry.payment_entry import get_reference_details
-	
+
 	for ref in doc.references:
 		payment_request_name = frappe.db.get_value("Payment Request",
 			{"reference_doctype": ref.reference_doctype, "reference_name": ref.reference_name,
@@ -430,7 +430,7 @@
 			ref_details = get_reference_details(ref.reference_doctype, ref.reference_name, doc.party_account_currency)
 			pay_req_doc = frappe.get_doc('Payment Request', payment_request_name)
 			status = pay_req_doc.status
-			
+
 			if status != "Paid" and not ref_details.outstanding_amount:
 				status = 'Paid'
 			elif status != "Partially Paid" and ref_details.outstanding_amount != ref_details.total_amount:
diff --git a/erpnext/accounts/doctype/payment_schedule/payment_schedule.json b/erpnext/accounts/doctype/payment_schedule/payment_schedule.json
index 1b38904..d363cf1 100644
--- a/erpnext/accounts/doctype/payment_schedule/payment_schedule.json
+++ b/erpnext/accounts/doctype/payment_schedule/payment_schedule.json
@@ -1,243 +1,82 @@
 {
- "allow_copy": 0, 
- "allow_guest_to_view": 0, 
- "allow_import": 0, 
- "allow_rename": 0, 
- "autoname": "", 
- "beta": 0, 
- "creation": "2017-08-10 15:38:00.080575", 
- "custom": 0, 
- "docstatus": 0, 
- "doctype": "DocType", 
- "document_type": "", 
- "editable_grid": 1, 
- "engine": "InnoDB", 
+ "actions": [],
+ "creation": "2017-08-10 15:38:00.080575",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "payment_term",
+  "description",
+  "due_date",
+  "invoice_portion",
+  "payment_amount",
+  "mode_of_payment",
+  "paid_amount"
+ ],
  "fields": [
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 2, 
-   "fieldname": "payment_term", 
-   "fieldtype": "Link", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Payment Term", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Payment Term", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 1, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "columns": 2,
+   "fieldname": "payment_term",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "label": "Payment Term",
+   "options": "Payment Term",
+   "print_hide": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 2, 
-   "fetch_from": "", 
-   "fieldname": "description", 
-   "fieldtype": "Small Text", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Description", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "columns": 2,
+   "fieldname": "description",
+   "fieldtype": "Small Text",
+   "in_list_view": 1,
+   "label": "Description"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 2, 
-   "fieldname": "due_date", 
-   "fieldtype": "Date", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Due Date", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 1, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "columns": 2,
+   "fieldname": "due_date",
+   "fieldtype": "Date",
+   "in_list_view": 1,
+   "label": "Due Date",
+   "reqd": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 2, 
-   "fetch_from": "", 
-   "fieldname": "invoice_portion", 
-   "fieldtype": "Percent", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Invoice Portion", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 1, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "columns": 2,
+   "fieldname": "invoice_portion",
+   "fieldtype": "Percent",
+   "in_list_view": 1,
+   "label": "Invoice Portion",
+   "print_hide": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 2, 
-   "fieldname": "payment_amount", 
-   "fieldtype": "Currency", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Payment Amount", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "currency", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 1, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "columns": 2,
+   "fieldname": "payment_amount",
+   "fieldtype": "Currency",
+   "in_list_view": 1,
+   "label": "Payment Amount",
+   "options": "currency",
+   "reqd": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "mode_of_payment", 
-   "fieldtype": "Link", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Mode of Payment", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Mode of Payment", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
+   "fieldname": "mode_of_payment",
+   "fieldtype": "Link",
+   "label": "Mode of Payment",
+   "options": "Mode of Payment"
+  },
+  {
+   "fieldname": "paid_amount",
+   "fieldtype": "Currency",
+   "label": "Paid Amount"
   }
- ], 
- "has_web_view": 0, 
- "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": "2018-09-06 17:35:44.580209", 
- "modified_by": "Administrator", 
- "module": "Accounts", 
- "name": "Payment Schedule", 
- "name_case": "", 
- "owner": "Administrator", 
- "permissions": [], 
- "quick_entry": 1, 
- "read_only": 0, 
- "read_only_onload": 0, 
- "show_name_in_global_search": 0, 
- "sort_field": "modified", 
- "sort_order": "DESC", 
- "track_changes": 1, 
- "track_seen": 0, 
- "track_views": 0
+ ],
+ "istable": 1,
+ "links": [],
+ "modified": "2020-03-13 17:58:24.729526",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "Payment 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/accounts/doctype/payment_terms_template/payment_terms_template.json b/erpnext/accounts/doctype/payment_terms_template/payment_terms_template.json
index 7a3483d..c4a2a88 100644
--- a/erpnext/accounts/doctype/payment_terms_template/payment_terms_template.json
+++ b/erpnext/accounts/doctype/payment_terms_template/payment_terms_template.json
@@ -1,164 +1,84 @@
 {
- "allow_copy": 0, 
- "allow_guest_to_view": 0, 
- "allow_import": 1, 
- "allow_rename": 1, 
- "autoname": "field:template_name", 
- "beta": 0, 
- "creation": "2017-08-10 15:34:28.058054", 
- "custom": 0, 
- "docstatus": 0, 
- "doctype": "DocType", 
- "document_type": "", 
- "editable_grid": 1, 
- "engine": "InnoDB", 
+ "actions": [],
+ "allow_import": 1,
+ "allow_rename": 1,
+ "autoname": "field:template_name",
+ "creation": "2017-08-10 15:34:28.058054",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "template_name",
+  "allocate_payment_based_on_payment_terms",
+  "terms"
+ ],
  "fields": [
   {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "template_name", 
-   "fieldtype": "Data", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Template Name", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "template_name",
+   "fieldtype": "Data",
+   "label": "Template Name",
+   "unique": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "terms", 
-   "fieldtype": "Table", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Payment Terms", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Payment Terms Template Detail", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 1, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "unique": 0
+   "fieldname": "terms",
+   "fieldtype": "Table",
+   "label": "Payment Terms",
+   "options": "Payment Terms Template Detail",
+   "reqd": 1
+  },
+  {
+   "default": "0",
+   "description": "If this checkbox is checked, paid amount will be splitted and allocated as per the amounts in payment schedule against each payment term",
+   "fieldname": "allocate_payment_based_on_payment_terms",
+   "fieldtype": "Check",
+   "label": "Allocate Payment Based On Payment Terms"
   }
- ], 
- "has_web_view": 0, 
- "hide_heading": 0, 
- "hide_toolbar": 0, 
- "idx": 0, 
- "image_view": 0, 
- "in_create": 0, 
- "is_submittable": 0, 
- "issingle": 0, 
- "istable": 0, 
- "max_attachments": 0, 
- "modified": "2018-01-24 11:13:31.158613", 
- "modified_by": "Administrator", 
- "module": "Accounts", 
- "name": "Payment Terms Template", 
- "name_case": "", 
- "owner": "Administrator", 
+ ],
+ "links": [],
+ "modified": "2020-04-01 15:35:18.112619",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "Payment Terms Template",
+ "owner": "Administrator",
  "permissions": [
   {
-   "amend": 0, 
-   "apply_user_permissions": 0, 
-   "cancel": 0, 
-   "create": 1, 
-   "delete": 1, 
-   "email": 1, 
-   "export": 1, 
-   "if_owner": 0, 
-   "import": 0, 
-   "permlevel": 0, 
-   "print": 1, 
-   "read": 1, 
-   "report": 1, 
-   "role": "System Manager", 
-   "set_user_permissions": 0, 
-   "share": 1, 
-   "submit": 0, 
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "export": 1,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "System Manager",
+   "share": 1,
    "write": 1
-  }, 
+  },
   {
-   "amend": 0, 
-   "apply_user_permissions": 0, 
-   "cancel": 0, 
-   "create": 1, 
-   "delete": 1, 
-   "email": 1, 
-   "export": 1, 
-   "if_owner": 0, 
-   "import": 0, 
-   "permlevel": 0, 
-   "print": 1, 
-   "read": 1, 
-   "report": 1, 
-   "role": "Accounts User", 
-   "set_user_permissions": 0, 
-   "share": 1, 
-   "submit": 0, 
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "export": 1,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "Accounts User",
+   "share": 1,
    "write": 1
-  }, 
+  },
   {
-   "amend": 0, 
-   "apply_user_permissions": 0, 
-   "cancel": 0, 
-   "create": 1, 
-   "delete": 1, 
-   "email": 1, 
-   "export": 1, 
-   "if_owner": 0, 
-   "import": 0, 
-   "permlevel": 0, 
-   "print": 1, 
-   "read": 1, 
-   "report": 1, 
-   "role": "Accounts Manager", 
-   "set_user_permissions": 0, 
-   "share": 1, 
-   "submit": 0, 
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "export": 1,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "Accounts Manager",
+   "share": 1,
    "write": 1
   }
- ], 
- "quick_entry": 0, 
- "read_only": 0, 
- "read_only_onload": 0, 
- "show_name_in_global_search": 0, 
- "sort_field": "modified", 
- "sort_order": "DESC", 
- "track_changes": 1, 
- "track_seen": 0
+ ],
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
 }
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/period_closing_voucher/period_closing_voucher.js b/erpnext/accounts/doctype/period_closing_voucher/period_closing_voucher.js
index 03b8f93..87e02fe 100644
--- a/erpnext/accounts/doctype/period_closing_voucher/period_closing_voucher.js
+++ b/erpnext/accounts/doctype/period_closing_voucher/period_closing_voucher.js
@@ -5,7 +5,7 @@
 	onload: function(frm) {
 		if (!frm.doc.transaction_date) frm.doc.transaction_date = frappe.datetime.obj_to_str(new Date());
 	},
-	
+
 	setup: function(frm) {
 		frm.set_query("closing_account_head", function() {
 			return {
@@ -18,9 +18,9 @@
 			}
 		});
 	},
-	
+
 	refresh: function(frm) {
-		if(frm.doc.docstatus==1) {
+		if(frm.doc.docstatus > 0) {
 			frm.add_custom_button(__('Ledger'), function() {
 				frappe.route_options = {
 					"voucher_no": frm.doc.name,
@@ -33,5 +33,5 @@
 			}, "fa fa-table");
 		}
 	}
-	
+
 })
diff --git a/erpnext/accounts/doctype/period_closing_voucher/period_closing_voucher.py b/erpnext/accounts/doctype/period_closing_voucher/period_closing_voucher.py
index eb95e45..bd8d8bd 100644
--- a/erpnext/accounts/doctype/period_closing_voucher/period_closing_voucher.py
+++ b/erpnext/accounts/doctype/period_closing_voucher/period_closing_voucher.py
@@ -17,8 +17,9 @@
 		self.make_gl_entries()
 
 	def on_cancel(self):
-		frappe.db.sql("""delete from `tabGL Entry`
-			where voucher_type = 'Period Closing Voucher' and voucher_no=%s""", self.name)
+		self.ignore_linked_doctypes = ('GL Entry', 'Stock Ledger Entry')
+		from erpnext.accounts.general_ledger import make_reverse_gl_entries
+		make_reverse_gl_entries(voucher_type="Period Closing Voucher", voucher_no=self.name)
 
 	def validate_account_head(self):
 		closing_account_type = frappe.db.get_value("Account", self.closing_account_head, "root_type")
diff --git a/erpnext/accounts/doctype/pos_profile_user/pos_profile_user.json b/erpnext/accounts/doctype/pos_profile_user/pos_profile_user.json
index 2fb66d2..59a673e 100644
--- a/erpnext/accounts/doctype/pos_profile_user/pos_profile_user.json
+++ b/erpnext/accounts/doctype/pos_profile_user/pos_profile_user.json
@@ -1,123 +1,39 @@
 {
- "allow_copy": 0, 
- "allow_guest_to_view": 0, 
- "allow_import": 0, 
- "allow_rename": 0, 
- "beta": 0, 
- "creation": "2017-10-27 16:46:06.060930", 
- "custom": 0, 
- "docstatus": 0, 
- "doctype": "DocType", 
- "document_type": "", 
- "editable_grid": 1, 
- "engine": "InnoDB", 
+ "actions": [],
+ "creation": "2017-10-27 16:46:06.060930",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "default",
+  "user"
+ ],
  "fields": [
   {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "default", 
-   "fieldtype": "Check", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Default", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "unique": 0
-  }, 
+   "default": "0",
+   "fieldname": "default",
+   "fieldtype": "Check",
+   "in_list_view": 1,
+   "label": "Default"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "user", 
-   "fieldtype": "Link", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "User", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "User", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "unique": 0
+   "fieldname": "user",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "label": "User",
+   "options": "User"
   }
- ], 
- "has_web_view": 0, 
- "hide_heading": 0, 
- "hide_toolbar": 0, 
- "idx": 0, 
- "image_view": 0, 
- "in_create": 0, 
- "is_submittable": 0, 
- "issingle": 0, 
- "istable": 0, 
- "max_attachments": 0, 
- "modified": "2017-11-23 17:13:16.005475", 
- "modified_by": "Administrator", 
- "module": "Accounts", 
- "name": "POS Profile User", 
- "name_case": "", 
- "owner": "Administrator", 
- "permissions": [
-  {
-   "amend": 0, 
-   "apply_user_permissions": 0, 
-   "cancel": 0, 
-   "create": 1, 
-   "delete": 1, 
-   "email": 1, 
-   "export": 1, 
-   "if_owner": 0, 
-   "import": 0, 
-   "permlevel": 0, 
-   "print": 1, 
-   "read": 1, 
-   "report": 1, 
-   "role": "System Manager", 
-   "set_user_permissions": 0, 
-   "share": 1, 
-   "submit": 0, 
-   "write": 1
-  }
- ], 
- "quick_entry": 1, 
- "read_only": 0, 
- "read_only_onload": 0, 
- "show_name_in_global_search": 0, 
- "sort_field": "modified", 
- "sort_order": "DESC", 
- "track_changes": 1, 
- "track_seen": 0
+ ],
+ "istable": 1,
+ "links": [],
+ "modified": "2020-05-01 09:46:47.599173",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "POS Profile User",
+ "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/accounts/doctype/pricing_rule/pricing_rule.py b/erpnext/accounts/doctype/pricing_rule/pricing_rule.py
index e13fcb9..19f571f 100644
--- a/erpnext/accounts/doctype/pricing_rule/pricing_rule.py
+++ b/erpnext/accounts/doctype/pricing_rule/pricing_rule.py
@@ -237,6 +237,7 @@
 			if pricing_rule.mixed_conditions or pricing_rule.apply_rule_on_other:
 				item_details.update({
 					'apply_rule_on_other_items': json.dumps(pricing_rule.apply_rule_on_other_items),
+					'price_or_product_discount': pricing_rule.price_or_product_discount,
 					'apply_rule_on': (frappe.scrub(pricing_rule.apply_rule_on_other)
 						if pricing_rule.apply_rule_on_other else frappe.scrub(pricing_rule.get('apply_on')))
 				})
diff --git a/erpnext/accounts/doctype/account_subtype/__init__.py b/erpnext/accounts/doctype/process_deferred_accounting/__init__.py
similarity index 100%
copy from erpnext/accounts/doctype/account_subtype/__init__.py
copy to erpnext/accounts/doctype/process_deferred_accounting/__init__.py
diff --git a/erpnext/accounts/doctype/process_deferred_accounting/process_deferred_accounting.js b/erpnext/accounts/doctype/process_deferred_accounting/process_deferred_accounting.js
new file mode 100644
index 0000000..975c60c
--- /dev/null
+++ b/erpnext/accounts/doctype/process_deferred_accounting/process_deferred_accounting.js
@@ -0,0 +1,39 @@
+// Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+frappe.ui.form.on('Process Deferred Accounting', {
+	setup: function(frm) {
+		frm.set_query("document_type", function() {
+			return {
+				filters: {
+					'name': ['in', ['Sales Invoice', 'Purchase Invoice']]
+				}
+			};
+		});
+	},
+
+	validate: function() {
+		return new Promise((resolve) => {
+			return frappe.db.get_single_value('Accounts Settings', 'automatically_process_deferred_accounting_entry')
+				.then(value => {
+					if(value) {
+						frappe.throw(__('Manual entry cannot be created! Disable automatic entry for deferred accounting in accounts settings and try again'));
+					}
+					resolve(value);
+				});
+		});
+	},
+
+	end_date: function(frm) {
+		if (frm.doc.end_date && frm.doc.end_date < frm.doc.start_date) {
+			frappe.throw(__("End date cannot be before start date"));
+		}
+	},
+
+	onload: function(frm) {
+		if (frm.doc.posting_date && frm.doc.docstatus === 0) {
+			frm.set_value('start_date', frappe.datetime.add_months(frm.doc.posting_date, -1));
+			frm.set_value('end_date', frm.doc.posting_date);
+		}
+	}
+});
diff --git a/erpnext/accounts/doctype/process_deferred_accounting/process_deferred_accounting.json b/erpnext/accounts/doctype/process_deferred_accounting/process_deferred_accounting.json
new file mode 100644
index 0000000..4daafef
--- /dev/null
+++ b/erpnext/accounts/doctype/process_deferred_accounting/process_deferred_accounting.json
@@ -0,0 +1,128 @@
+{
+ "actions": [],
+ "autoname": "ACC-PDA-.#####",
+ "creation": "2019-11-04 18:01:23.454775",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "company",
+  "type",
+  "account",
+  "column_break_3",
+  "posting_date",
+  "start_date",
+  "end_date",
+  "amended_from"
+ ],
+ "fields": [
+  {
+   "fieldname": "type",
+   "fieldtype": "Select",
+   "in_list_view": 1,
+   "label": "Type",
+   "options": "\nIncome\nExpense",
+   "reqd": 1
+  },
+  {
+   "fieldname": "amended_from",
+   "fieldtype": "Link",
+   "label": "Amended From",
+   "no_copy": 1,
+   "options": "Process Deferred Accounting",
+   "print_hide": 1,
+   "read_only": 1
+  },
+  {
+   "fieldname": "start_date",
+   "fieldtype": "Date",
+   "in_list_view": 1,
+   "label": "Service Start Date",
+   "reqd": 1
+  },
+  {
+   "fieldname": "end_date",
+   "fieldtype": "Date",
+   "in_list_view": 1,
+   "label": "Service End Date",
+   "reqd": 1
+  },
+  {
+   "fieldname": "column_break_3",
+   "fieldtype": "Column Break"
+  },
+  {
+   "default": "Today",
+   "fieldname": "posting_date",
+   "fieldtype": "Date",
+   "in_list_view": 1,
+   "label": "Posting Date",
+   "reqd": 1
+  },
+  {
+   "fieldname": "account",
+   "fieldtype": "Link",
+   "label": "Account",
+   "options": "Account"
+  },
+  {
+   "fieldname": "company",
+   "fieldtype": "Link",
+   "label": "Company",
+   "options": "Company",
+   "reqd": 1
+  }
+ ],
+ "is_submittable": 1,
+ "links": [],
+ "modified": "2020-02-06 18:18:09.852844",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "Process Deferred Accounting",
+ "owner": "Administrator",
+ "permissions": [
+  {
+   "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
+  },
+  {
+   "cancel": 1,
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "export": 1,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "Accounts Manager",
+   "share": 1,
+   "submit": 1,
+   "write": 1
+  },
+  {
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "export": 1,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "Accounts User",
+   "share": 1,
+   "submit": 1,
+   "write": 1
+  }
+ ],
+ "sort_field": "modified",
+ "sort_order": "DESC"
+}
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/process_deferred_accounting/process_deferred_accounting.py b/erpnext/accounts/doctype/process_deferred_accounting/process_deferred_accounting.py
new file mode 100644
index 0000000..0eac732
--- /dev/null
+++ b/erpnext/accounts/doctype/process_deferred_accounting/process_deferred_accounting.py
@@ -0,0 +1,34 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+import erpnext
+from frappe import _
+from frappe.model.document import Document
+from erpnext.accounts.general_ledger import make_reverse_gl_entries
+from erpnext.accounts.deferred_revenue import convert_deferred_expense_to_expense, \
+	convert_deferred_revenue_to_income, build_conditions
+
+class ProcessDeferredAccounting(Document):
+	def validate(self):
+		if self.end_date < self.start_date:
+			frappe.throw(_("End date cannot be before start date"))
+
+	def on_submit(self):
+		conditions = build_conditions(self.type, self.account, self.company)
+		if self.type == 'Income':
+			convert_deferred_revenue_to_income(self.name, self.start_date, self.end_date, conditions)
+		else:
+			convert_deferred_expense_to_expense(self.name, self.start_date, self.end_date, conditions)
+
+	def on_cancel(self):
+		self.ignore_linked_doctypes = ['GL Entry']
+		gl_entries = frappe.get_all('GL Entry', fields = ['*'],
+			filters={
+				'against_voucher_type': self.doctype,
+				'against_voucher': self.name
+			})
+
+		make_reverse_gl_entries(gl_entries=gl_entries)
\ No newline at end of file
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
new file mode 100644
index 0000000..31356c6
--- /dev/null
+++ b/erpnext/accounts/doctype/process_deferred_accounting/test_process_deferred_accounting.py
@@ -0,0 +1,48 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and Contributors
+# See license.txt
+from __future__ import unicode_literals
+
+import frappe
+import unittest
+from erpnext.accounts.doctype.account.test_account import create_account
+from erpnext.stock.doctype.item.test_item import create_item
+from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice, check_gl_entries
+
+class TestProcessDeferredAccounting(unittest.TestCase):
+	def test_creation_of_ledger_entry_on_submit(self):
+		''' test creation of gl entries on submission of document '''
+		deferred_account = create_account(account_name="Deferred Revenue",
+			parent_account="Current Liabilities - _TC", company="_Test Company")
+
+		item = create_item("_Test Item for Deferred Accounting")
+		item.enable_deferred_revenue = 1
+		item.deferred_revenue_account = deferred_account
+		item.no_of_months = 12
+		item.save()
+
+		si = create_sales_invoice(item=item.name, 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"
+		si.items[0].deferred_revenue_account = deferred_account
+		si.save()
+		si.submit()
+
+		process_deferred_accounting = doc = frappe.get_doc(dict(
+			doctype='Process Deferred Accounting',
+			posting_date="2019-01-01",
+			start_date="2019-01-01",
+			end_date="2019-01-31",
+			type="Income"
+		))
+
+		process_deferred_accounting.insert()
+		process_deferred_accounting.submit()
+
+		expected_gle = [
+			[deferred_account, 33.85, 0.0, "2019-01-31"],
+			["Sales - _TC", 0.0, 33.85, "2019-01-31"]
+		]
+
+		check_gl_entries(self, si.name, expected_gle, "2019-01-10")
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
index 9292b63..4f6be59 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
@@ -261,12 +261,25 @@
 				price_list: this.frm.doc.buying_price_list
 			}, function() {
 				me.apply_pricing_rule();
-
 				me.frm.doc.apply_tds = me.frm.supplier_tds ? 1 : 0;
+				me.frm.doc.tax_withholding_category = me.frm.supplier_tds;
 				me.frm.set_df_property("apply_tds", "read_only", me.frm.supplier_tds ? 0 : 1);
+				me.frm.set_df_property("tax_withholding_category", "hidden", me.frm.supplier_tds ? 0 : 1);
 			})
 	},
 
+	apply_tds: function(frm) {
+		var me = this;
+
+		if (!me.frm.doc.apply_tds) {
+			me.frm.set_value("tax_withholding_category", '');
+			me.frm.set_df_property("tax_withholding_category", "hidden", 1);
+		} else {
+			me.frm.set_value("tax_withholding_category", me.frm.supplier_tds);
+			me.frm.set_df_property("tax_withholding_category", "hidden", 0);
+		}
+	},
+
 	credit_to: function() {
 		var me = this;
 		if(this.frm.doc.credit_to) {
@@ -369,11 +382,6 @@
 	cur_frm.refresh_fields();
 }
 
-cur_frm.cscript.update_stock = function(doc, dt, dn) {
-	hide_fields(doc, dt, dn);
-	this.frm.fields_dict.items.grid.toggle_reqd("item_code", doc.update_stock? true: false)
-}
-
 cur_frm.fields_dict.cash_bank_account.get_query = function(doc) {
 	return {
 		filters: [
@@ -515,5 +523,10 @@
 			erpnext.buying.get_default_bom(frm);
 		}
 		frm.toggle_reqd("supplier_warehouse", frm.doc.is_subcontracted==="Yes");
+	},
+
+	update_stock: function(frm) {
+		hide_fields(frm.doc);
+		frm.fields_dict.items.grid.toggle_reqd("item_code", frm.doc.update_stock? true: false);
 	}
 })
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
index 0e09454..98ba5c7 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
@@ -13,6 +13,7 @@
   "supplier_name",
   "tax_id",
   "due_date",
+  "tax_withholding_category",
   "column_break1",
   "company",
   "posting_date",
@@ -1294,13 +1295,21 @@
    "fieldtype": "Check",
    "label": "Is Internal Supplier",
    "read_only": 1
+  },
+  {
+   "fieldname": "tax_withholding_category",
+   "fieldtype": "Link",
+   "hidden": 1,
+   "label": "Tax Withholding Category",
+   "options": "Tax Withholding Category",
+   "print_hide": 1
   }
  ],
  "icon": "fa fa-file-text",
  "idx": 204,
  "is_submittable": 1,
  "links": [],
- "modified": "2020-04-17 13:05:25.199832",
+ "modified": "2020-04-18 13:05:25.199832",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "Purchase Invoice",
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
index 0283d30..3aa24df 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
@@ -14,7 +14,7 @@
 from erpnext.accounts.utils import get_account_currency, get_fiscal_year
 from erpnext.stock.doctype.purchase_receipt.purchase_receipt import update_billed_amount_based_on_po
 from erpnext.stock import get_warehouse_account_map
-from erpnext.accounts.general_ledger import make_gl_entries, merge_similar_entries, delete_gl_entries
+from erpnext.accounts.general_ledger import make_gl_entries, merge_similar_entries, make_reverse_gl_entries
 from erpnext.accounts.doctype.gl_entry.gl_entry import update_outstanding_amt
 from erpnext.buying.utils import check_on_hold_or_closed_status
 from erpnext.accounts.general_ledger import get_round_off_account_and_cost_center
@@ -382,7 +382,7 @@
 		self.update_project()
 		update_linked_doc(self.doctype, self.name, self.inter_company_invoice_reference)
 
-	def make_gl_entries(self, gl_entries=None, repost_future_gle=True, from_repost=False):
+	def make_gl_entries(self, gl_entries=None):
 		if not self.grand_total:
 			return
 		if not gl_entries:
@@ -391,21 +391,17 @@
 		if gl_entries:
 			update_outstanding = "No" if (cint(self.is_paid) or self.write_off_account) else "Yes"
 
-			make_gl_entries(gl_entries,  cancel=(self.docstatus == 2),
-				update_outstanding=update_outstanding, merge_entries=False, from_repost=from_repost)
+			if self.docstatus == 1:
+				make_gl_entries(gl_entries, update_outstanding=update_outstanding, merge_entries=False)
+			elif self.docstatus == 2:
+				make_reverse_gl_entries(voucher_type=self.doctype, voucher_no=self.name)
 
 			if update_outstanding == "No":
 				update_outstanding_amt(self.credit_to, "Supplier", self.supplier,
 					self.doctype, self.return_against if cint(self.is_return) and self.return_against else self.name)
 
-			if (repost_future_gle or self.flags.repost_future_gle) and cint(self.update_stock) and self.auto_accounting_for_stock:
-				from erpnext.controllers.stock_controller import update_gl_entries_after
-				items, warehouses = self.get_items_and_warehouses()
-				update_gl_entries_after(self.posting_date, self.posting_time,
-					warehouses, items, company = self.company)
-
 		elif self.docstatus == 2 and cint(self.update_stock) and self.auto_accounting_for_stock:
-			delete_gl_entries(voucher_type=self.doctype, voucher_no=self.name)
+			make_reverse_gl_entries(voucher_type=self.doctype, voucher_no=self.name)
 
 	def get_gl_entries(self, warehouse_account=None):
 		self.auto_accounting_for_stock = erpnext.is_perpetual_inventory_enabled(self.company)
@@ -934,6 +930,7 @@
 		frappe.db.set(self, 'status', 'Cancelled')
 
 		unlink_inter_company_doc(self.doctype, self.name, self.inter_company_invoice_reference)
+		self.ignore_linked_doctypes = ('GL Entry', 'Stock Ledger Entry')
 
 	def update_project(self):
 		project_list = []
@@ -1002,7 +999,7 @@
 		if not self.apply_tds:
 			return
 
-		tax_withholding_details = get_party_tax_withholding_details(self)
+		tax_withholding_details = get_party_tax_withholding_details(self, self.tax_withholding_category)
 
 		if not tax_withholding_details:
 			return
diff --git a/erpnext/accounts/doctype/purchase_invoice/test_records.json b/erpnext/accounts/doctype/purchase_invoice/test_records.json
index 171927c..7030faf 100644
--- a/erpnext/accounts/doctype/purchase_invoice/test_records.json
+++ b/erpnext/accounts/doctype/purchase_invoice/test_records.json
@@ -138,13 +138,12 @@
     "row_id": 7
    }
   ],
-  "posting_date": "2013-02-03",
   "supplier": "_Test Supplier",
   "supplier_name": "_Test Supplier"
  },
- 
- 
- 
+
+
+
  {
   "bill_no": "NA",
   "buying_price_list": "_Test Price List",
@@ -204,7 +203,6 @@
     "tax_amount": 150.0
    }
   ],
-  "posting_date": "2013-02-03",
   "supplier": "_Test Supplier",
   "supplier_name": "_Test Supplier"
  }
diff --git a/erpnext/accounts/doctype/purchase_taxes_and_charges/purchase_taxes_and_charges.json b/erpnext/accounts/doctype/purchase_taxes_and_charges/purchase_taxes_and_charges.json
index 1741869..0e748f8 100644
--- a/erpnext/accounts/doctype/purchase_taxes_and_charges/purchase_taxes_and_charges.json
+++ b/erpnext/accounts/doctype/purchase_taxes_and_charges/purchase_taxes_and_charges.json
@@ -1,4 +1,5 @@
 {
+ "actions": [],
  "autoname": "hash",
  "creation": "2013-05-21 16:16:04",
  "doctype": "DocType",
@@ -14,11 +15,11 @@
   "col_break1",
   "account_head",
   "description",
+  "section_break_10",
+  "rate",
   "accounting_dimensions_section",
   "cost_center",
   "dimension_col_break",
-  "section_break_10",
-  "rate",
   "section_break_9",
   "tax_amount",
   "tax_amount_after_discount_amount",
@@ -27,8 +28,7 @@
   "base_tax_amount",
   "base_total",
   "base_tax_amount_after_discount_amount",
-  "item_wise_tax_detail",
-  "parenttype"
+  "item_wise_tax_detail"
  ],
  "fields": [
   {
@@ -53,6 +53,7 @@
   },
   {
    "columns": 2,
+   "default": "On Net Total",
    "fieldname": "charge_type",
    "fieldtype": "Select",
    "in_list_view": 1,
@@ -197,15 +198,6 @@
    "read_only": 1
   },
   {
-   "fieldname": "parenttype",
-   "fieldtype": "Data",
-   "hidden": 1,
-   "label": "Parenttype",
-   "oldfieldname": "parenttype",
-   "oldfieldtype": "Data",
-   "print_hide": 1
-  },
-  {
    "fieldname": "accounting_dimensions_section",
    "fieldtype": "Section Break",
    "label": "Accounting Dimensions"
@@ -217,11 +209,14 @@
  ],
  "idx": 1,
  "istable": 1,
- "modified": "2019-05-25 23:08:38.281025",
+ "links": [],
+ "modified": "2020-03-12 14:53:47.679439",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "Purchase Taxes and Charges",
  "owner": "Administrator",
  "permissions": [],
+ "sort_field": "modified",
+ "sort_order": "DESC",
  "track_changes": 1
 }
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/sales_invoice/regional/india.js b/erpnext/accounts/doctype/sales_invoice/regional/india.js
index ba6c03b..6336db1 100644
--- a/erpnext/accounts/doctype/sales_invoice/regional/india.js
+++ b/erpnext/accounts/doctype/sales_invoice/regional/india.js
@@ -26,16 +26,24 @@
 			&& !frm.doc.is_return && !frm.doc.ewaybill) {
 
 			frm.add_custom_button('E-Way Bill JSON', () => {
-				var w = window.open(
-					frappe.urllib.get_full_url(
-						"/api/method/erpnext.regional.india.utils.generate_ewb_json?"
-						+ "dt=" + encodeURIComponent(frm.doc.doctype)
-						+ "&dn=" + encodeURIComponent(frm.doc.name)
-					)
-				);
-				if (!w) {
-					frappe.msgprint(__("Please enable pop-ups")); return;
-				}
+				frappe.call({
+					method: 'erpnext.regional.india.utils.generate_ewb_json',
+					args: {
+						'dt': frm.doc.doctype,
+						'dn': [frm.doc.name]
+					},
+					callback: function(r) {
+						if (r.message) {
+							const args = {
+								cmd: 'erpnext.regional.india.utils.download_ewb_json',
+								data: r.message,
+								docname: frm.doc.name
+							};
+							open_url_post(frappe.request.url, args);
+						}
+					}
+				});
+
 			}, __("Create"));
 		}
 	}
diff --git a/erpnext/accounts/doctype/sales_invoice/regional/india_list.js b/erpnext/accounts/doctype/sales_invoice/regional/india_list.js
index d175827..3e1c522 100644
--- a/erpnext/accounts/doctype/sales_invoice/regional/india_list.js
+++ b/erpnext/accounts/doctype/sales_invoice/regional/india_list.js
@@ -16,17 +16,23 @@
 			}
 		}
 
-		var w = window.open(
-			frappe.urllib.get_full_url(
-				"/api/method/erpnext.regional.india.utils.generate_ewb_json?"
-				+ "dt=" + encodeURIComponent(doclist.doctype)
-				+ "&dn=" + encodeURIComponent(docnames)
-			)
-		);
-		if (!w) {
-			frappe.msgprint(__("Please enable pop-ups")); return;
-		}
-
+		frappe.call({
+			method: 'erpnext.regional.india.utils.generate_ewb_json',
+			args: {
+				'dt': doclist.doctype,
+				'dn': docnames
+			},
+			callback: function(r) {
+				if (r.message) {
+					const args = {
+						cmd: 'erpnext.regional.india.utils.download_ewb_json',
+						data: r.message,
+						docname: docnames
+					};
+					open_url_post(frappe.request.url, args);
+				}
+			}
+		});
 	};
 
 	doclist.page.add_actions_menu_item(__('Generate E-Way Bill JSON'), action, false);
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
index 6f78db2..f248276 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
@@ -32,6 +32,7 @@
 			me.frm.script_manager.trigger("is_pos");
 			me.frm.refresh_fields();
 		}
+		erpnext.queries.setup_warehouse_query(this.frm);
 	},
 
 	refresh: function(doc, dt, dn) {
@@ -344,7 +345,7 @@
 
 	set_dynamic_labels: function() {
 		this._super();
-		this.hide_fields(this.frm.doc);
+		this.frm.events.hide_fields(this.frm)
 	},
 
 	items_on_form_rendered: function() {
@@ -403,7 +404,7 @@
 							if(r.message && r.message.print_format) {
 								me.frm.pos_print_format = r.message.print_format;
 							}
-							me.frm.script_manager.trigger("update_stock");
+							me.frm.trigger("update_stock");
 							if(me.frm.doc.taxes_and_charges) {
 								me.frm.script_manager.trigger("taxes_and_charges");
 							}
@@ -445,35 +446,6 @@
 // for backward compatibility: combine new and previous states
 $.extend(cur_frm.cscript, new erpnext.accounts.SalesInvoiceController({frm: cur_frm}));
 
-// Hide Fields
-// ------------
-cur_frm.cscript.hide_fields = function(doc) {
-	var parent_fields = ['project', 'due_date', 'is_opening', 'source', 'total_advance', 'get_advances',
-		'advances', 'from_date', 'to_date'];
-
-	if(cint(doc.is_pos) == 1) {
-		hide_field(parent_fields);
-	} else {
-		for (var i in parent_fields) {
-			var docfield = frappe.meta.docfield_map[doc.doctype][parent_fields[i]];
-			if(!docfield.hidden) unhide_field(parent_fields[i]);
-		}
-	}
-
-	// India related fields
-	if (frappe.boot.sysdefaults.country == 'India') unhide_field(['c_form_applicable', 'c_form_no']);
-	else hide_field(['c_form_applicable', 'c_form_no']);
-
-	this.frm.toggle_enable("write_off_amount", !!!cint(doc.write_off_outstanding_amount_automatically));
-
-	cur_frm.refresh_fields();
-}
-
-cur_frm.cscript.update_stock = function(doc, dt, dn) {
-	cur_frm.cscript.hide_fields(doc, dt, dn);
-	this.frm.fields_dict.items.grid.toggle_reqd("item_code", doc.update_stock? true: false)
-}
-
 cur_frm.cscript['Make Delivery Note'] = function() {
 	frappe.model.open_mapped_doc({
 		method: "erpnext.accounts.doctype.sales_invoice.sales_invoice.make_delivery_note",
@@ -586,7 +558,9 @@
 		frm.set_query("account_for_change_amount", function() {
 			return {
 				filters: {
-					account_type: ['in', ["Cash", "Bank"]]
+					account_type: ['in', ["Cash", "Bank"]],
+					company: frm.doc.company,
+					is_group: 0
 				}
 			};
 		});
@@ -667,7 +641,8 @@
 		frm.fields_dict["loyalty_redemption_account"].get_query = function() {
 			return {
 				filters:{
-					"company": frm.doc.company
+					"company": frm.doc.company,
+					"is_group": 0
 				}
 			}
 		};
@@ -676,7 +651,8 @@
 		frm.fields_dict["loyalty_redemption_cost_center"].get_query = function() {
 			return {
 				filters:{
-					"company": frm.doc.company
+					"company": frm.doc.company,
+					"is_group": 0
 				}
 			}
 		};
@@ -714,6 +690,12 @@
 		frm.redemption_conversion_factor = null;
 	},
 
+	update_stock: function(frm, dt, dn) {
+		frm.events.hide_fields(frm);
+		frm.fields_dict.items.grid.toggle_reqd("item_code", frm.doc.update_stock);
+		frm.trigger('reset_posting_time');
+	},
+
 	redeem_loyalty_points: function(frm) {
 		frm.events.get_loyalty_details(frm);
 	},
@@ -737,6 +719,29 @@
 		}
 	},
 
+	hide_fields: function(frm) {
+		let doc = frm.doc;
+		var parent_fields = ['project', 'due_date', 'is_opening', 'source', 'total_advance', 'get_advances',
+		'advances', 'from_date', 'to_date'];
+
+		if(cint(doc.is_pos) == 1) {
+			hide_field(parent_fields);
+		} else {
+			for (var i in parent_fields) {
+				var docfield = frappe.meta.docfield_map[doc.doctype][parent_fields[i]];
+				if(!docfield.hidden) unhide_field(parent_fields[i]);
+			}
+		}
+
+		// India related fields
+		if (frappe.boot.sysdefaults.country == 'India') unhide_field(['c_form_applicable', 'c_form_no']);
+		else hide_field(['c_form_applicable', 'c_form_no']);
+
+		frm.toggle_enable("write_off_amount", !!!cint(doc.write_off_outstanding_amount_automatically));
+
+		frm.refresh_fields();
+	},
+
 	get_loyalty_details: function(frm) {
 		if (frm.doc.customer && frm.doc.redeem_loyalty_points) {
 			frappe.call({
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json
index 918fa14..db20589 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json
@@ -149,9 +149,9 @@
   "edit_printing_settings",
   "letter_head",
   "group_same_items",
-  "language",
-  "column_break_84",
   "select_print_heading",
+  "column_break_84",
+  "language",
   "more_information",
   "inter_company_invoice_reference",
   "is_internal_customer",
@@ -1579,7 +1579,7 @@
  "idx": 181,
  "is_submittable": 1,
  "links": [],
- "modified": "2020-04-17 12:38:41.435728",
+ "modified": "2020-04-29 13:37:09.355300",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "Sales Invoice",
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
index 3c40112..3b0fade 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
@@ -7,7 +7,6 @@
 from frappe.utils import cint, flt, add_months, today, date_diff, getdate, add_days, cstr, nowdate
 from frappe import _, msgprint, throw
 from erpnext.accounts.party import get_party_account, get_due_date
-from erpnext.controllers.stock_controller import update_gl_entries_after
 from frappe.model.mapper import get_mapped_doc
 from erpnext.accounts.doctype.sales_invoice.pos import update_multi_mode_option
 
@@ -282,6 +281,8 @@
 		if "Healthcare" in active_domains:
 			manage_invoice_submit_cancel(self, "on_cancel")
 
+		self.ignore_linked_doctypes = ('GL Entry', 'Stock Ledger Entry')
+
 	def update_status_updater_args(self):
 		if cint(self.update_stock):
 			self.status_updater.append({
@@ -717,7 +718,9 @@
 			if d.delivery_note and frappe.db.get_value("Delivery Note", d.delivery_note, "docstatus") != 1:
 				throw(_("Delivery Note {0} is not submitted").format(d.delivery_note))
 
-	def make_gl_entries(self, gl_entries=None, repost_future_gle=True, from_repost=False):
+	def make_gl_entries(self, gl_entries=None):
+		from erpnext.accounts.general_ledger import make_reverse_gl_entries
+
 		auto_accounting_for_stock = erpnext.is_perpetual_inventory_enabled(self.company)
 		if not gl_entries:
 			gl_entries = self.get_gl_entries()
@@ -729,23 +732,19 @@
 			update_outstanding = "No" if (cint(self.is_pos) or self.write_off_account or
 				cint(self.redeem_loyalty_points)) else "Yes"
 
-			make_gl_entries(gl_entries, cancel=(self.docstatus == 2),
-				update_outstanding=update_outstanding, merge_entries=False, from_repost=from_repost)
+			if self.docstatus == 1:
+				make_gl_entries(gl_entries, update_outstanding=update_outstanding, merge_entries=False)
+			elif self.docstatus == 2:
+				make_reverse_gl_entries(voucher_type=self.doctype, voucher_no=self.name)
 
 			if update_outstanding == "No":
 				from erpnext.accounts.doctype.gl_entry.gl_entry import update_outstanding_amt
 				update_outstanding_amt(self.debit_to, "Customer", self.customer,
 					self.doctype, self.return_against if cint(self.is_return) and self.return_against else self.name)
 
-			if (repost_future_gle or self.flags.repost_future_gle) and cint(self.update_stock) \
-				and cint(auto_accounting_for_stock):
-					items, warehouses = self.get_items_and_warehouses()
-					update_gl_entries_after(self.posting_date, self.posting_time,
-						warehouses, items, company = self.company)
 		elif self.docstatus == 2 and cint(self.update_stock) \
 			and cint(auto_accounting_for_stock):
-				from erpnext.accounts.general_ledger import delete_gl_entries
-				delete_gl_entries(voucher_type=self.doctype, voucher_no=self.name)
+				make_reverse_gl_entries(voucher_type=self.doctype, voucher_no=self.name)
 
 	def get_gl_entries(self, warehouse_account=None):
 		from erpnext.accounts.general_ledger import merge_similar_entries
diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
index a2819af..c82a249 100644
--- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
@@ -5,7 +5,7 @@
 import frappe
 
 import unittest, copy, time
-from frappe.utils import nowdate, flt, getdate, cint, add_days
+from frappe.utils import nowdate, flt, getdate, cint, add_days, add_months
 from frappe.model.dynamic_links import get_dynamic_link_map
 from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry, get_qty_after_transaction
 from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import unlink_payment_on_cancel_of_invoice
@@ -364,7 +364,7 @@
 		gle = frappe.db.sql("""select * from `tabGL Entry`
 			where voucher_type='Sales Invoice' and voucher_no=%s""", si.name)
 
-		self.assertFalse(gle)
+		self.assertTrue(gle)
 
 	def test_tax_calculation_with_multiple_items(self):
 		si = create_sales_invoice(qty=84, rate=4.6, do_not_save=True)
@@ -678,14 +678,15 @@
 		gle = frappe.db.sql("""select * from `tabGL Entry`
 			where voucher_type='Sales Invoice' and voucher_no=%s""", si.name)
 
-		self.assertFalse(gle)
+		self.assertTrue(gle)
 
 	def test_pos_gl_entry_with_perpetual_inventory(self):
 		make_pos_profile()
 
-		pr = make_purchase_receipt(company= "_Test Company with perpetual inventory",supplier_warehouse= "Work In Progress - TCP1", item_code= "_Test FG Item",warehouse= "Stores - TCP1",cost_center= "Main - TCP1")
+		pr = make_purchase_receipt(company= "_Test Company with perpetual inventory", item_code= "_Test FG Item",warehouse= "Stores - TCP1",cost_center= "Main - TCP1")
 
-		pos = create_sales_invoice(company= "_Test Company with perpetual inventory", debit_to="Debtors - TCP1", item_code= "_Test FG Item", warehouse="Stores - TCP1", income_account = "Sales - TCP1", expense_account = "Cost of Goods Sold - TCP1", cost_center = "Main - TCP1", do_not_save=True)
+		pos = create_sales_invoice(company= "_Test Company with perpetual inventory", debit_to="Debtors - TCP1", item_code= "_Test FG Item", warehouse="Stores - TCP1",
+			income_account = "Sales - TCP1", expense_account = "Cost of Goods Sold - TCP1", cost_center = "Main - TCP1", do_not_save=True)
 
 		pos.is_pos = 1
 		pos.update_stock = 1
@@ -766,9 +767,13 @@
 	def test_pos_change_amount(self):
 		make_pos_profile()
 
-		pr = make_purchase_receipt(company= "_Test Company with perpetual inventory",supplier_warehouse= "Work In Progress - TCP1", item_code= "_Test FG Item",warehouse= "Stores - TCP1",cost_center= "Main - TCP1")
+		pr = make_purchase_receipt(company= "_Test Company with perpetual inventory",
+			item_code= "_Test FG Item",warehouse= "Stores - TCP1", cost_center= "Main - TCP1")
 
-		pos = create_sales_invoice(company= "_Test Company with perpetual inventory", debit_to="Debtors - TCP1", item_code= "_Test FG Item", warehouse="Stores - TCP1", income_account = "Sales - TCP1", expense_account = "Cost of Goods Sold - TCP1", cost_center = "Main - TCP1", do_not_save=True)
+		pos = create_sales_invoice(company= "_Test Company with perpetual inventory",
+			debit_to="Debtors - TCP1", item_code= "_Test FG Item", warehouse="Stores - TCP1",
+			income_account = "Sales - TCP1", expense_account = "Cost of Goods Sold - TCP1",
+			cost_center = "Main - TCP1", do_not_save=True)
 
 		pos.is_pos = 1
 		pos.update_stock = 1
@@ -787,8 +792,15 @@
 		from erpnext.accounts.doctype.sales_invoice.pos import make_invoice
 
 		pos_profile = make_pos_profile()
-		pr = make_purchase_receipt(company= "_Test Company with perpetual inventory",supplier_warehouse= "Work In Progress - TCP1", item_code= "_Test FG Item",warehouse= "Stores - TCP1",cost_center= "Main - TCP1")
-		pos = create_sales_invoice(company= "_Test Company with perpetual inventory", debit_to="Debtors - TCP1", item_code= "_Test FG Item", warehouse="Stores - TCP1", income_account = "Sales - TCP1", expense_account = "Cost of Goods Sold - TCP1", cost_center = "Main - TCP1", do_not_save=True)
+
+		pr = make_purchase_receipt(company= "_Test Company with perpetual inventory",
+			item_code= "_Test FG Item",
+			warehouse= "Stores - TCP1", cost_center= "Main - TCP1")
+
+		pos = create_sales_invoice(company= "_Test Company with perpetual inventory",
+			debit_to="Debtors - TCP1", item_code= "_Test FG Item", warehouse="Stores - TCP1",
+			income_account = "Sales - TCP1", expense_account = "Cost of Goods Sold - TCP1",
+			cost_center = "Main - TCP1", do_not_save=True)
 
 		pos.is_pos = 1
 		pos.update_stock = 1
@@ -891,11 +903,9 @@
 		gle = frappe.db.sql("""select * from `tabGL Entry`
 			where voucher_type='Sales Invoice' and voucher_no=%s""", si.name)
 
-		self.assertFalse(gle)
-
+		self.assertTrue(gle)
 
 		frappe.db.sql("delete from `tabPOS Profile`")
-		si.delete()
 
 	def test_pos_si_without_payment(self):
 		set_perpetual_inventory()
@@ -1012,9 +1022,6 @@
 
 		si.cancel()
 
-		self.assertTrue(not frappe.db.sql("""select name from `tabJournal Entry Account`
-			where reference_name=%s""", si.name))
-
 	def test_serialized(self):
 		from erpnext.stock.doctype.stock_entry.test_stock_entry import make_serialized_item
 		from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos
@@ -1230,7 +1237,7 @@
 		gle = frappe.db.sql("""select name from `tabGL Entry`
 			where voucher_type='Sales Invoice' and voucher_no=%s""", si.name)
 
-		self.assertFalse(gle)
+		self.assertTrue(gle)
 
 	def test_invalid_currency(self):
 		# Customer currency = USD
@@ -1714,37 +1721,76 @@
 		si.submit()
 
 		from erpnext.accounts.deferred_revenue import convert_deferred_revenue_to_income
-		convert_deferred_revenue_to_income(start_date="2019-01-01", end_date="2019-01-31")
+
+		pda1 = frappe.get_doc(dict(
+			doctype='Process Deferred Accounting',
+			posting_date=nowdate(),
+			start_date="2019-01-01",
+			end_date="2019-03-31",
+			type="Income",
+			company="_Test Company"
+		))
+
+		pda1.insert()
+		pda1.submit()
 
 		expected_gle = [
 			[deferred_account, 33.85, 0.0, "2019-01-31"],
-			["Sales - _TC", 0.0, 33.85, "2019-01-31"]
-		]
-
-		self.check_gl_entries(si.name, expected_gle, "2019-01-10")
-
-		convert_deferred_revenue_to_income(start_date="2019-01-01", end_date="2019-03-31")
-
-		expected_gle = [
+			["Sales - _TC", 0.0, 33.85, "2019-01-31"],
 			[deferred_account, 43.08, 0.0, "2019-02-28"],
 			["Sales - _TC", 0.0, 43.08, "2019-02-28"],
 			[deferred_account, 23.07, 0.0, "2019-03-15"],
 			["Sales - _TC", 0.0, 23.07, "2019-03-15"]
 		]
 
-		self.check_gl_entries(si.name, expected_gle, "2019-01-31")
+		check_gl_entries(self, si.name, expected_gle, "2019-01-30")
 
-	def check_gl_entries(self, voucher_no, expected_gle, posting_date):
-		gl_entries = frappe.db.sql("""select account, debit, credit, posting_date
-			from `tabGL Entry`
-			where voucher_type='Sales Invoice' and voucher_no=%s and posting_date > %s
-			order by posting_date asc, account asc""", (voucher_no, posting_date), as_dict=1)
+	def test_deferred_error_email(self):
+		deferred_account = create_account(account_name="Deferred Revenue",
+			parent_account="Current Liabilities - _TC", company="_Test Company")
 
-		for i, gle in enumerate(gl_entries):
-			self.assertEqual(expected_gle[i][0], gle.account)
-			self.assertEqual(expected_gle[i][1], gle.debit)
-			self.assertEqual(expected_gle[i][2], gle.credit)
-			self.assertEqual(getdate(expected_gle[i][3]), gle.posting_date)
+		item = create_item("_Test Item for Deferred Accounting")
+		item.enable_deferred_revenue = 1
+		item.deferred_revenue_account = deferred_account
+		item.no_of_months = 12
+		item.save()
+
+		si = create_sales_invoice(item=item.name, 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"
+		si.items[0].deferred_revenue_account = deferred_account
+		si.save()
+		si.submit()
+
+		from erpnext.accounts.deferred_revenue import convert_deferred_revenue_to_income
+
+		acc_settings = frappe.get_doc('Accounts Settings', 'Accounts Settings')
+		acc_settings.acc_frozen_upto = '2019-01-31'
+		acc_settings.save()
+
+		pda = frappe.get_doc(dict(
+			doctype='Process Deferred Accounting',
+			posting_date=nowdate(),
+			start_date="2019-01-01",
+			end_date="2019-03-31",
+			type="Income",
+			company="_Test Company"
+		))
+
+		pda.insert()
+		pda.submit()
+
+		email = frappe.db.sql(""" select name from `tabEmail Queue`
+		where message like %(txt)s """, {
+			'txt': "%%%s%%" % "Error while processing deferred accounting for {0}".format(pda.name)
+		})
+
+		self.assertTrue(email)
+
+		acc_settings.load_from_db()
+		acc_settings.acc_frozen_upto = None
+		acc_settings.save()
 
 	def test_inter_company_transaction(self):
 
@@ -1892,7 +1938,7 @@
 
 		si.submit()
 
-		data = get_ewb_data("Sales Invoice", si.name)
+		data = get_ewb_data("Sales Invoice", [si.name])
 
 		self.assertEqual(data['version'], '1.0.1118')
 		self.assertEqual(data['billLists'][0]['fromGstin'], '27AAECE4835E1ZR')
@@ -1905,6 +1951,18 @@
 		self.assertEqual(data['billLists'][0]['vehicleNo'], 'KA12KA1234')
 		self.assertEqual(data['billLists'][0]['itemList'][0]['taxableAmount'], 60000)
 
+def check_gl_entries(doc, voucher_no, expected_gle, posting_date):
+	gl_entries = frappe.db.sql("""select account, debit, credit, posting_date
+		from `tabGL Entry`
+		where voucher_type='Sales Invoice' and voucher_no=%s and posting_date > %s
+		order by posting_date asc, account asc""", (voucher_no, posting_date), as_dict=1)
+
+	for i, gle in enumerate(gl_entries):
+		doc.assertEqual(expected_gle[i][0], gle.account)
+		doc.assertEqual(expected_gle[i][1], gle.debit)
+		doc.assertEqual(expected_gle[i][2], gle.credit)
+		doc.assertEqual(getdate(expected_gle[i][3]), gle.posting_date)
+
 	def test_item_tax_validity(self):
 		item = frappe.get_doc("Item", "_Test Item 2")
 
diff --git a/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py b/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py
index 6c31e9e..dd6b4fd 100644
--- a/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py
+++ b/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py
@@ -6,23 +6,42 @@
 import frappe
 from frappe import _
 from frappe.model.document import Document
-from frappe.utils import flt
+from frappe.utils import flt, getdate
 from erpnext.accounts.utils import get_fiscal_year
 
 class TaxWithholdingCategory(Document):
 	pass
 
-def get_party_tax_withholding_details(ref_doc):
-	tax_withholding_category = frappe.db.get_value('Supplier', ref_doc.supplier, 'tax_withholding_category')
+def get_party_tax_withholding_details(ref_doc, tax_withholding_category=None):
+
+	pan_no = ''
+	suppliers = []
+
+	if not tax_withholding_category:
+		tax_withholding_category, pan_no = frappe.db.get_value('Supplier', ref_doc.supplier, ['tax_withholding_category', 'pan'])
+
 	if not tax_withholding_category:
 		return
 
+	if not pan_no:
+		pan_no = frappe.db.get_value('Supplier', ref_doc.supplier, 'pan')
+
+	# Get others suppliers with the same PAN No
+	if pan_no:
+		suppliers = [d.name for d in  frappe.get_all('Supplier', fields=['name'], filters={'pan': pan_no})]
+
+	if not suppliers:
+		suppliers.append(ref_doc.supplier)
+
 	fy = get_fiscal_year(ref_doc.posting_date, company=ref_doc.company)
 	tax_details = get_tax_withholding_details(tax_withholding_category, fy[0], ref_doc.company)
 	if not tax_details:
 		frappe.throw(_('Please set associated account in Tax Withholding Category {0} against Company {1}')
 			.format(tax_withholding_category, ref_doc.company))
-	tds_amount = get_tds_amount(ref_doc, tax_details, fy)
+
+	tds_amount = get_tds_amount(suppliers, ref_doc.net_total, ref_doc.company,
+		tax_details, fy,  ref_doc.posting_date, pan_no)
+
 	tax_row = get_tax_row(tax_details, tds_amount)
 
 	return tax_row
@@ -51,6 +70,7 @@
 	frappe.throw(_("No Tax Withholding data found for the current Fiscal Year."))
 
 def get_tax_row(tax_details, tds_amount):
+
 	return {
 		"category": "Total",
 		"add_deduct_tax": "Deduct",
@@ -60,25 +80,36 @@
 		"tax_amount": tds_amount
 	}
 
-def get_tds_amount(ref_doc, tax_details, fiscal_year_details):
+def get_tds_amount(suppliers, net_total, company, tax_details, fiscal_year_details, posting_date, pan_no=None):
 	fiscal_year, year_start_date, year_end_date = fiscal_year_details
 	tds_amount = 0
 	tds_deducted = 0
 
-	def _get_tds(amount):
+	def _get_tds(amount, rate):
 		if amount <= 0:
 			return 0
 
-		return amount * tax_details.rate / 100
+		return amount * rate / 100
+
+	ldc_name = frappe.db.get_value('Lower Deduction Certificate',
+		{
+			'pan_no': pan_no,
+			'fiscal_year': fiscal_year
+		}, 'name')
+	ldc = ''
+
+	if ldc_name:
+		ldc = frappe.get_doc('Lower Deduction Certificate', ldc_name)
 
 	entries = frappe.db.sql("""
 			select voucher_no, credit
 			from `tabGL Entry`
-			where party=%s and fiscal_year=%s and credit > 0
-		""", (ref_doc.supplier, fiscal_year), as_dict=1)
+			where company = %s and
+			party in %s and fiscal_year=%s and credit > 0
+		""", (company, tuple(suppliers), fiscal_year), as_dict=1)
 
 	vouchers = [d.voucher_no for d in entries]
-	advance_vouchers = get_advance_vouchers(ref_doc.supplier, fiscal_year)
+	advance_vouchers = get_advance_vouchers(suppliers, fiscal_year=fiscal_year, company=company)
 
 	tds_vouchers = vouchers + advance_vouchers
 
@@ -93,7 +124,20 @@
 		tds_deducted = tds_deducted[0][0] if tds_deducted and tds_deducted[0][0] else 0
 
 	if tds_deducted:
-		tds_amount = _get_tds(ref_doc.net_total)
+		if ldc:
+			limit_consumed = frappe.db.get_value('Purchase Invoice',
+				{
+					'supplier': ('in', suppliers),
+					'apply_tds': 1,
+					'docstatus': 1
+				}, 'sum(net_total)')
+
+		if ldc and is_valid_certificate(ldc.valid_from, ldc.valid_upto, posting_date, limit_consumed, net_total,
+			ldc.certificate_limit):
+
+			tds_amount = get_ltds_amount(net_total, limit_consumed, ldc.certificate_limit, ldc.rate, tax_details)
+		else:
+			tds_amount = _get_tds(net_total, tax_details.rate)
 	else:
 		supplier_credit_amount = frappe.get_all('Purchase Invoice Item',
 			fields = ['sum(net_amount)'],
@@ -106,43 +150,79 @@
 			fields = ['sum(credit_in_account_currency)'],
 			filters = {
 				'parent': ('in', vouchers), 'docstatus': 1,
-				'party': ref_doc.supplier,
+				'party': ('in', suppliers),
 				'reference_type': ('not in', ['Purchase Invoice'])
 			}, as_list=1)
 
 		supplier_credit_amount += (jv_supplier_credit_amt[0][0]
 			if jv_supplier_credit_amt and jv_supplier_credit_amt[0][0] else 0)
 
-		supplier_credit_amount += ref_doc.net_total
+		supplier_credit_amount += net_total
 
-		debit_note_amount = get_debit_note_amount(ref_doc.supplier, year_start_date, year_end_date)
+		debit_note_amount = get_debit_note_amount(suppliers, year_start_date, year_end_date)
 		supplier_credit_amount -= debit_note_amount
 
 		if ((tax_details.get('threshold', 0) and supplier_credit_amount >= tax_details.threshold)
 			or (tax_details.get('cumulative_threshold', 0) and supplier_credit_amount >= tax_details.cumulative_threshold)):
-			tds_amount = _get_tds(supplier_credit_amount)
+
+			if ldc and is_valid_certificate(ldc.valid_from, ldc.valid_upto, posting_date, tds_deducted, net_total,
+				ldc.certificate_limit):
+				tds_amount = get_ltds_amount(supplier_credit_amount, 0, ldc.certificate_limit, ldc.rate,
+					tax_details)
+			else:
+				tds_amount = _get_tds(supplier_credit_amount, tax_details.rate)
 
 	return tds_amount
 
-def get_advance_vouchers(supplier, fiscal_year=None, company=None, from_date=None, to_date=None):
+def get_advance_vouchers(suppliers, fiscal_year=None, company=None, from_date=None, to_date=None):
 	condition = "fiscal_year=%s" % fiscal_year
+
+	if company:
+		condition += "and company =%s" % (company)
 	if from_date and to_date:
-		condition = "company=%s and posting_date between %s and %s" % (company, from_date, to_date)
+		condition += "and posting_date between %s and %s" % (company, from_date, to_date)
+
+	## Appending the same supplier again if length of suppliers list is 1
+	## since tuple of single element list contains None, For example ('Test Supplier 1', )
+	## and the below query fails
+	if len(suppliers) == 1:
+		suppliers.append(suppliers[0])
 
 	return frappe.db.sql_list("""
 		select distinct voucher_no
 		from `tabGL Entry`
-		where party=%s and %s and debit > 0
-	""", (supplier, condition)) or []
+		where party in %s and %s and debit > 0
+	""", (tuple(suppliers), condition)) or []
 
-def get_debit_note_amount(supplier, year_start_date, year_end_date, company=None):
-	condition = ""
+def get_debit_note_amount(suppliers, year_start_date, year_end_date, company=None):
+	condition = "and 1=1"
 	if company:
 		condition = " and company=%s " % company
 
+	if len(suppliers) == 1:
+		suppliers.append(suppliers[0])
+
 	return flt(frappe.db.sql("""
 		select abs(sum(net_total))
 		from `tabPurchase Invoice`
-		where supplier=%s %s and is_return=1 and docstatus=1
-			and posting_date between %s and %s
-	""", (supplier, condition, year_start_date, year_end_date)))
\ No newline at end of file
+		where supplier in %s and is_return=1 and docstatus=1
+			and posting_date between %s and %s %s
+	""", (tuple(suppliers), year_start_date, year_end_date, condition)))
+
+def get_ltds_amount(current_amount, deducted_amount, certificate_limit, rate, tax_details):
+	if current_amount < (certificate_limit - deducted_amount):
+		return current_amount * rate/100
+	else:
+		ltds_amount = (certificate_limit - deducted_amount)
+		tds_amount = current_amount - ltds_amount
+
+		return ltds_amount * rate/100 + tds_amount * tax_details.rate/100
+
+def is_valid_certificate(valid_from, valid_upto, posting_date, deducted_amount, current_amount, certificate_limit):
+	valid = False
+
+	if ((getdate(valid_from) <= getdate(posting_date) <= getdate(valid_upto)) and
+			certificate_limit > deducted_amount):
+		valid = True
+
+	return valid
\ No newline at end of file
diff --git a/erpnext/accounts/general_ledger.py b/erpnext/accounts/general_ledger.py
index 5ba455c..fb1a4f4 100644
--- a/erpnext/accounts/general_ledger.py
+++ b/erpnext/accounts/general_ledger.py
@@ -3,7 +3,7 @@
 
 from __future__ import unicode_literals
 import frappe, erpnext
-from frappe.utils import flt, cstr, cint, comma_and
+from frappe.utils import flt, cstr, cint, comma_and, today, getdate, formatdate, now
 from frappe import _
 from erpnext.accounts.utils import get_stock_and_account_balance
 from frappe.model.meta import get_field_precision
@@ -15,17 +15,17 @@
 class StockAccountInvalidTransaction(frappe.ValidationError): pass
 class StockValueAndAccountBalanceOutOfSync(frappe.ValidationError): pass
 
-def make_gl_entries(gl_map, cancel=False, adv_adj=False, merge_entries=True, update_outstanding='Yes', from_repost=False):
+def make_gl_entries(gl_map, cancel=False, adv_adj=False, merge_entries=True, update_outstanding='Yes'):
 	if gl_map:
 		if not cancel:
 			validate_accounting_period(gl_map)
 			gl_map = process_gl_map(gl_map, merge_entries)
 			if gl_map and len(gl_map) > 1:
-				save_entries(gl_map, adv_adj, update_outstanding, from_repost)
+				save_entries(gl_map, adv_adj, update_outstanding)
 			else:
 				frappe.throw(_("Incorrect number of General Ledger Entries found. You might have selected a wrong Account in the transaction."))
 		else:
-			delete_gl_entries(gl_map, adv_adj=adv_adj, update_outstanding=update_outstanding)
+			make_reverse_gl_entries(gl_map, adv_adj=adv_adj, update_outstanding=update_outstanding)
 
 def validate_accounting_period(gl_map):
 	accounting_periods = frappe.db.sql(""" SELECT
@@ -119,33 +119,36 @@
 		if same_head:
 			return e
 
-def save_entries(gl_map, adv_adj, update_outstanding, from_repost=False):
-	if not from_repost:
-		validate_cwip_accounts(gl_map)
+def save_entries(gl_map, adv_adj, update_outstanding):
+	validate_cwip_accounts(gl_map)
 
 	round_off_debit_credit(gl_map)
+
+	if gl_map:
+		check_freezing_date(gl_map[0]["posting_date"], adv_adj)
+
 	for entry in gl_map:
-		make_entry(entry, adv_adj, update_outstanding, from_repost)
+		make_entry(entry, adv_adj, update_outstanding)
 
 		# check against budget
-		if not from_repost:
-			validate_expense_against_budget(entry)
+		validate_expense_against_budget(entry)
 
-	if not from_repost:
-		validate_account_for_perpetual_inventory(gl_map)
+	validate_account_for_perpetual_inventory(gl_map)
 
 
-def make_entry(args, adv_adj, update_outstanding, from_repost=False):
+def make_entry(args, adv_adj, update_outstanding):
 	gle = frappe.new_doc("GL Entry")
 	gle.update(args)
 	gle.flags.ignore_permissions = 1
-	gle.flags.from_repost = from_repost
 	gle.validate()
 	gle.db_insert()
-	gle.run_method("on_update_with_args", adv_adj, update_outstanding, from_repost)
+	gle.run_method("on_update_with_args", adv_adj, update_outstanding)
 	gle.flags.ignore_validate = True
 	gle.submit()
 
+	# check against budget
+	validate_expense_against_budget(args)
+
 def validate_account_for_perpetual_inventory(gl_map):
 	if cint(erpnext.is_perpetual_inventory_enabled(gl_map[0].company)):
 		account_list = [gl_entries.account for gl_entries in gl_map]
@@ -169,33 +172,33 @@
 						.format(account), StockAccountInvalidTransaction)
 
 			# This has been comment for a temporary, will add this code again on release of immutable ledger
-			# elif account_bal != stock_bal:
-			# 	precision = get_field_precision(frappe.get_meta("GL Entry").get_field("debit"),
-			# 		currency=frappe.get_cached_value('Company',  gl_map[0].company,  "default_currency"))
+			elif account_bal != stock_bal:
+				precision = get_field_precision(frappe.get_meta("GL Entry").get_field("debit"),
+					currency=frappe.get_cached_value('Company',  gl_map[0].company,  "default_currency"))
 
-			# 	diff = flt(stock_bal - account_bal, precision)
-			# 	error_reason = _("Stock Value ({0}) and Account Balance ({1}) are out of sync for account {2} and it's linked warehouses.").format(
-			# 		stock_bal, account_bal, frappe.bold(account))
-			# 	error_resolution = _("Please create adjustment Journal Entry for amount {0} ").format(frappe.bold(diff))
-			# 	stock_adjustment_account = frappe.db.get_value("Company",gl_map[0].company,"stock_adjustment_account")
+				diff = flt(stock_bal - account_bal, precision)
+				error_reason = _("Stock Value ({0}) and Account Balance ({1}) are out of sync for account {2} and it's linked warehouses.").format(
+					stock_bal, account_bal, frappe.bold(account))
+				error_resolution = _("Please create adjustment Journal Entry for amount {0} ").format(frappe.bold(diff))
+				stock_adjustment_account = frappe.db.get_value("Company",gl_map[0].company,"stock_adjustment_account")
 
-			# 	db_or_cr_warehouse_account =('credit_in_account_currency' if diff < 0 else 'debit_in_account_currency')
-			# 	db_or_cr_stock_adjustment_account = ('debit_in_account_currency' if diff < 0 else 'credit_in_account_currency')
+				db_or_cr_warehouse_account =('credit_in_account_currency' if diff < 0 else 'debit_in_account_currency')
+				db_or_cr_stock_adjustment_account = ('debit_in_account_currency' if diff < 0 else 'credit_in_account_currency')
 
-			# 	journal_entry_args = {
-			# 	'accounts':[
-			# 		{'account': account, db_or_cr_warehouse_account : abs(diff)},
-			# 		{'account': stock_adjustment_account, db_or_cr_stock_adjustment_account : abs(diff) }]
-			# 	}
+				journal_entry_args = {
+				'accounts':[
+					{'account': account, db_or_cr_warehouse_account : abs(diff)},
+					{'account': stock_adjustment_account, db_or_cr_stock_adjustment_account : abs(diff) }]
+				}
 
-			# 	frappe.msgprint(msg="""{0}<br></br>{1}<br></br>""".format(error_reason, error_resolution),
-			# 		raise_exception=StockValueAndAccountBalanceOutOfSync,
-			# 		title=_('Values Out Of Sync'),
-			# 		primary_action={
-			# 			'label': _('Make Journal Entry'),
-			# 			'client_action': 'erpnext.route_to_adjustment_jv',
-			# 			'args': journal_entry_args
-			# 		})
+				frappe.msgprint(msg="""{0}<br></br>{1}<br></br>""".format(error_reason, error_resolution),
+					raise_exception=StockValueAndAccountBalanceOutOfSync,
+					title=_('Values Out Of Sync'),
+					primary_action={
+						'label': _('Make Journal Entry'),
+						'client_action': 'erpnext.route_to_adjustment_jv',
+						'args': journal_entry_args
+					})
 
 def validate_cwip_accounts(gl_map):
 	cwip_enabled = any([cint(ac.enable_cwip_accounting) for ac in frappe.db.get_all("Asset Category","enable_cwip_accounting")])
@@ -282,31 +285,64 @@
 
 	return round_off_account, round_off_cost_center
 
-def delete_gl_entries(gl_entries=None, voucher_type=None, voucher_no=None,
-		adv_adj=False, update_outstanding="Yes"):
-
-	from erpnext.accounts.doctype.gl_entry.gl_entry import validate_balance_type, \
-		check_freezing_date, update_outstanding_amt, validate_frozen_account
+def make_reverse_gl_entries(gl_entries=None, voucher_type=None, voucher_no=None,
+	adv_adj=False, update_outstanding="Yes"):
+	"""
+		Get original gl entries of the voucher
+		and make reverse gl entries by swapping debit and credit
+	"""
 
 	if not gl_entries:
-		gl_entries = frappe.db.sql("""
-			select account, posting_date, party_type, party, cost_center, fiscal_year,voucher_type,
-			voucher_no, against_voucher_type, against_voucher, cost_center, company
-			from `tabGL Entry`
-			where voucher_type=%s and voucher_no=%s""", (voucher_type, voucher_no), as_dict=True)
+		gl_entries = frappe.get_all("GL Entry",
+			fields = ["*"],
+			filters = {
+				"voucher_type": voucher_type,
+				"voucher_no": voucher_no
+			})
 
 	if gl_entries:
+		set_as_cancel(gl_entries[0]['voucher_type'], gl_entries[0]['voucher_no'])
 		check_freezing_date(gl_entries[0]["posting_date"], adv_adj)
 
-	frappe.db.sql("""delete from `tabGL Entry` where voucher_type=%s and voucher_no=%s""",
-		(voucher_type or gl_entries[0]["voucher_type"], voucher_no or gl_entries[0]["voucher_no"]))
+		for entry in gl_entries:
+			entry['name'] = None
+			debit = entry.get('debit', 0)
+			credit = entry.get('credit', 0)
 
-	for entry in gl_entries:
-		validate_frozen_account(entry["account"], adv_adj)
-		validate_balance_type(entry["account"], adv_adj)
-		if not adv_adj:
-			validate_expense_against_budget(entry)
+			debit_in_account_currency = entry.get('debit_in_account_currency', 0)
+			credit_in_account_currency = entry.get('credit_in_account_currency', 0)
 
-		if entry.get("against_voucher") and update_outstanding == 'Yes' and not adv_adj:
-			update_outstanding_amt(entry["account"], entry.get("party_type"), entry.get("party"), entry.get("against_voucher_type"),
-				entry.get("against_voucher"), on_cancel=True)
+			entry['debit'] = credit
+			entry['credit'] = debit
+			entry['debit_in_account_currency'] = credit_in_account_currency
+			entry['credit_in_account_currency'] = debit_in_account_currency
+
+			entry['remarks'] = "On cancellation of " + entry['voucher_no']
+			entry['is_cancelled'] = 1
+			entry['posting_date'] = today()
+
+			if entry['debit'] or entry['credit']:
+				make_entry(entry, adv_adj, "Yes")
+
+
+def check_freezing_date(posting_date, adv_adj=False):
+	"""
+		Nobody can do GL Entries where posting date is before freezing date
+		except authorized person
+	"""
+	if not adv_adj:
+		acc_frozen_upto = frappe.db.get_value('Accounts Settings', None, 'acc_frozen_upto')
+		if acc_frozen_upto:
+			frozen_accounts_modifier = frappe.db.get_value( 'Accounts Settings', None,'frozen_accounts_modifier')
+			if getdate(posting_date) <= getdate(acc_frozen_upto) \
+					and not frozen_accounts_modifier in frappe.get_roles():
+				frappe.throw(_("You are not authorized to add or update entries before {0}").format(formatdate(acc_frozen_upto)))
+
+def set_as_cancel(voucher_type, voucher_no):
+	"""
+		Set is_cancelled=1 in all original gl entries for the voucher
+	"""
+	frappe.db.sql("""update `tabGL Entry` set is_cancelled = 1,
+		modified=%s, modified_by=%s
+		where voucher_type=%s and voucher_no=%s and is_cancelled = 0""",
+		(now(), frappe.session.user, voucher_type, voucher_no))
diff --git a/erpnext/accounts/party.py b/erpnext/accounts/party.py
index 47dfa09..6e5b33f 100644
--- a/erpnext/accounts/party.py
+++ b/erpnext/accounts/party.py
@@ -600,10 +600,12 @@
 	else:
 		return ''
 
-def get_partywise_advanced_payment_amount(party_type, posting_date = None):
+def get_partywise_advanced_payment_amount(party_type, posting_date = None, company=None):
 	cond = "1=1"
 	if posting_date:
 		cond = "posting_date <= '{0}'".format(posting_date)
+	if company:
+		cond += "and company = '{0}'".format(company)
 
 	data = frappe.db.sql(""" SELECT party, sum({0}) as amount
 		FROM `tabGL Entry`
diff --git a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py
index 240b0d8..e9c286f 100755
--- a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py
+++ b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py
@@ -344,26 +344,28 @@
 	def allocate_outstanding_based_on_payment_terms(self, row):
 		self.get_payment_terms(row)
 		for term in row.payment_terms:
-			term.outstanding = term.invoiced
 
 			# update "paid" and "oustanding" for this term
-			self.allocate_closing_to_term(row, term, 'paid')
+			if not term.paid:
+				self.allocate_closing_to_term(row, term, 'paid')
 
 			# update "credit_note" and "oustanding" for this term
 			if term.outstanding:
 				self.allocate_closing_to_term(row, term, 'credit_note')
 
+		row.payment_terms = sorted(row.payment_terms, key=lambda x: x['due_date'])
+
 	def get_payment_terms(self, row):
 		# build payment_terms for row
 		payment_terms_details = frappe.db.sql("""
 			select
 				si.name, si.party_account_currency, si.currency, si.conversion_rate,
-				ps.due_date, ps.payment_amount, ps.description
+				ps.due_date, ps.payment_amount, ps.description, ps.paid_amount
 			from `tab{0}` si, `tabPayment Schedule` ps
 			where
 				si.name = ps.parent and
 				si.name = %s
-			order by ps.due_date
+			order by ps.paid_amount desc, due_date
 		""".format(row.voucher_type), row.voucher_no, as_dict = 1)
 
 
@@ -389,11 +391,14 @@
 			"invoiced": invoiced,
 			"invoice_grand_total": row.invoiced,
 			"payment_term": d.description,
-			"paid": 0.0,
+			"paid": d.paid_amount,
 			"credit_note": 0.0,
-			"outstanding": 0.0
+			"outstanding": invoiced - d.paid_amount
 		}))
 
+		if d.paid_amount:
+			row['paid'] -= d.paid_amount
+
 	def allocate_closing_to_term(self, row, term, key):
 		if row[key]:
 			if row[key] > term.outstanding:
diff --git a/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.py b/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.py
index b607c0f..aa6b42e 100644
--- a/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.py
+++ b/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.py
@@ -33,7 +33,7 @@
 		self.get_party_total(args)
 
 		party_advance_amount = get_partywise_advanced_payment_amount(self.party_type,
-			self.filters.report_date) or {}
+			self.filters.report_date, self.filters.company) or {}
 
 		for party, party_dict in iteritems(self.party_total):
 			if party_dict.outstanding == 0:
diff --git a/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.py b/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.py
index b62238b..c2c7207 100644
--- a/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.py
+++ b/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.py
@@ -84,6 +84,7 @@
 
 def get_profit_loss_data(fiscal_year, companies, columns, filters):
 	income, expense, net_profit_loss = get_income_expense_data(companies, fiscal_year, filters)
+	company_currency = get_company_currency(filters)
 
 	data = []
 	data.extend(income or [])
@@ -93,7 +94,7 @@
 
 	chart = get_pl_chart_data(filters, columns, income, expense, net_profit_loss)
 
-	report_summary = get_pl_summary(companies, '', income, expense, net_profit_loss, True)
+	report_summary = get_pl_summary(companies, '', income, expense, net_profit_loss, company_currency, True)
 
 	return data, None, chart, report_summary
 
diff --git a/erpnext/accounts/report/general_ledger/general_ledger.js b/erpnext/accounts/report/general_ledger/general_ledger.js
index ac49d37..1188bea 100644
--- a/erpnext/accounts/report/general_ledger/general_ledger.js
+++ b/erpnext/accounts/report/general_ledger/general_ledger.js
@@ -154,8 +154,12 @@
 		{
 			"fieldname": "include_default_book_entries",
 			"label": __("Include Default Book Entries"),
-			"fieldtype": "Check",
-			"default": 1
+			"fieldtype": "Check"
+		},
+		{
+			"fieldname": "show_cancelled_entries",
+			"label": __("Show Cancelled Entries"),
+			"fieldtype": "Check"
 		}
 	]
 }
diff --git a/erpnext/accounts/report/general_ledger/general_ledger.py b/erpnext/accounts/report/general_ledger/general_ledger.py
index f776d93..7af5fa8 100644
--- a/erpnext/accounts/report/general_ledger/general_ledger.py
+++ b/erpnext/accounts/report/general_ledger/general_ledger.py
@@ -188,6 +188,9 @@
 		else:
 			conditions.append("finance_book in (%(finance_book)s)")
 
+	if not filters.get("show_cancelled_entries"):
+		conditions.append("is_cancelled = 0")
+
 	from frappe.desk.reportview import build_match_conditions
 	match_conditions = build_match_conditions("GL Entry")
 
diff --git a/erpnext/accounts/report/gross_and_net_profit_report/gross_and_net_profit_report.py b/erpnext/accounts/report/gross_and_net_profit_report/gross_and_net_profit_report.py
index 6550981..1c45810 100644
--- a/erpnext/accounts/report/gross_and_net_profit_report/gross_and_net_profit_report.py
+++ b/erpnext/accounts/report/gross_and_net_profit_report/gross_and_net_profit_report.py
@@ -8,7 +8,6 @@
 from erpnext.accounts.report.financial_statements import (get_period_list, get_columns, get_data)
 import copy
 
-
 def execute(filters=None):
 	period_list = get_period_list(filters.from_fiscal_year, filters.to_fiscal_year,
 		filters.periodicity, filters.accumulated_values, filters.company)
@@ -27,17 +26,25 @@
 
 
 	gross_income = get_revenue(income, period_list)
-
 	gross_expense = get_revenue(expense, period_list)
 
 	if(len(gross_income)==0 and len(gross_expense)== 0):
-		data.append({"account_name": "'" + _("Nothing is included in gross") + "'",
-		"account": "'" + _("Nothing is included in gross") + "'"})
-
+		data.append({
+			"account_name": "'" + _("Nothing is included in gross") + "'",
+			"account": "'" + _("Nothing is included in gross") + "'"
+		})
 		return columns, data
 
-	data.append({"account_name": "'" + _("Included in Gross Profit") + "'",
-		"account": "'" + _("Included in Gross Profit") + "'"})
+	# to avoid error eg: gross_income[0] : list index out of range
+	if not gross_income:
+		gross_income = [{}]
+	if not gross_expense:
+		gross_expense = [{}]
+
+	data.append({
+		"account_name": "'" + _("Included in Gross Profit") + "'",
+		"account": "'" + _("Included in Gross Profit") + "'"
+	})
 
 	data.append({})
 	data.extend(gross_income or [])
@@ -111,7 +118,6 @@
 
 
 def get_profit(gross_income, gross_expense, period_list, company, profit_type, currency=None, consolidated=False):
-
 	profit_loss = {
 		"account_name": "'" + _(profit_type) + "'",
 		"account": "'" + _(profit_type) + "'",
@@ -123,7 +129,9 @@
 
 	for period in period_list:
 		key = period if consolidated else period.key
-		profit_loss[key] = flt(gross_income[0].get(key, 0)) - flt(gross_expense[0].get(key, 0))
+		gross_income_for_period = flt(gross_income[0].get(key, 0)) if gross_income else 0
+		gross_expense_for_period = flt(gross_expense[0].get(key, 0)) if gross_expense else 0
+		profit_loss[key] = gross_income_for_period - gross_expense_for_period
 
 		if profit_loss[key]:
 			has_value=True
@@ -143,12 +151,18 @@
 
 	for period in period_list:
 		key = period if consolidated else period.key
-		total_income = flt(gross_income[0].get(key, 0)) + flt(non_gross_income[0].get(key, 0))
-		total_expense = flt(gross_expense[0].get(key, 0)) + flt(non_gross_expense[0].get(key, 0))
+		gross_income_for_period = flt(gross_income[0].get(key, 0)) if gross_income else 0
+		non_gross_income_for_period = flt(non_gross_income[0].get(key, 0)) if non_gross_income else 0
+
+		gross_expense_for_period = flt(gross_expense[0].get(key, 0)) if gross_expense else 0
+		non_gross_expense_for_period = flt(non_gross_expense[0].get(key, 0)) if non_gross_expense else 0
+
+		total_income = gross_income_for_period + non_gross_income_for_period
+		total_expense = gross_expense_for_period + non_gross_expense_for_period
 		profit_loss[key] = flt(total_income) - flt(total_expense)
 
 		if profit_loss[key]:
 			has_value=True
 
 	if has_value:
-		return profit_loss
+		return profit_loss
\ No newline at end of file
diff --git a/erpnext/accounts/report/gross_profit/gross_profit.py b/erpnext/accounts/report/gross_profit/gross_profit.py
index 6ef6d6e..4e22b05 100644
--- a/erpnext/accounts/report/gross_profit/gross_profit.py
+++ b/erpnext/accounts/report/gross_profit/gross_profit.py
@@ -55,27 +55,27 @@
 	columns = []
 	column_map = frappe._dict({
 		"parent": _("Sales Invoice") + ":Link/Sales Invoice:120",
-		"posting_date": _("Posting Date") + ":Date",
-		"posting_time": _("Posting Time"),
-		"item_code": _("Item Code") + ":Link/Item",
-		"item_name": _("Item Name"),
-		"item_group": _("Item Group") + ":Link/Item Group",
-		"brand": _("Brand"),
-		"description": _("Description"),
-		"warehouse": _("Warehouse") + ":Link/Warehouse",
-		"qty": _("Qty") + ":Float",
-		"base_rate": _("Avg. Selling Rate") + ":Currency/currency",
-		"buying_rate": _("Valuation Rate") + ":Currency/currency",
-		"base_amount": _("Selling Amount") + ":Currency/currency",
-		"buying_amount": _("Buying Amount") + ":Currency/currency",
-		"gross_profit": _("Gross Profit") + ":Currency/currency",
-		"gross_profit_percent": _("Gross Profit %") + ":Percent",
-		"project": _("Project") + ":Link/Project",
+		"posting_date": _("Posting Date") + ":Date:100",
+		"posting_time": _("Posting Time") + ":Data:100",
+		"item_code": _("Item Code") + ":Link/Item:100",
+		"item_name": _("Item Name") + ":Data:100",
+		"item_group": _("Item Group") + ":Link/Item Group:100",
+		"brand": _("Brand") + ":Link/Brand:100",
+		"description": _("Description") +":Data:100",
+		"warehouse": _("Warehouse") + ":Link/Warehouse:100",
+		"qty": _("Qty") + ":Float:80",
+		"base_rate": _("Avg. Selling Rate") + ":Currency/currency:100",
+		"buying_rate": _("Valuation Rate") + ":Currency/currency:100",
+		"base_amount": _("Selling Amount") + ":Currency/currency:100",
+		"buying_amount": _("Buying Amount") + ":Currency/currency:100",
+		"gross_profit": _("Gross Profit") + ":Currency/currency:100",
+		"gross_profit_percent": _("Gross Profit %") + ":Percent:100",
+		"project": _("Project") + ":Link/Project:100",
 		"sales_person": _("Sales person"),
-		"allocated_amount": _("Allocated Amount") + ":Currency/currency",
-		"customer": _("Customer") + ":Link/Customer",
-		"customer_group": _("Customer Group") + ":Link/Customer Group",
-		"territory": _("Territory") + ":Link/Territory"
+		"allocated_amount": _("Allocated Amount") + ":Currency/currency:100",
+		"customer": _("Customer") + ":Link/Customer:100",
+		"customer_group": _("Customer Group") + ":Link/Customer Group:100",
+		"territory": _("Territory") + ":Link/Territory:100"
 	})
 
 	for col in group_wise_columns.get(scrub(filters.group_by)):
@@ -85,7 +85,8 @@
 		"fieldname": "currency",
 		"label" : _("Currency"),
 		"fieldtype": "Link",
-		"options": "Currency"
+		"options": "Currency",
+		"hidden": 1
 	})
 
 	return columns
@@ -277,7 +278,7 @@
 			from `tabPurchase Invoice Item` a
 			where a.item_code = %s and a.docstatus=1
 			and modified <= %s
-			order by a.modified desc limit 1""", (item_code,self.filters.to_date))
+			order by a.modified desc limit 1""", (item_code, self.filters.to_date))
 		else:
 			last_purchase_rate = frappe.db.sql("""
 			select (a.base_rate / a.conversion_factor)
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 127f313..1f78c7a 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
@@ -102,7 +102,7 @@
 
 		data.append(row)
 
-	if filters.get('group_by'):
+	if filters.get('group_by') and item_list:
 		total_row = total_row_map.get(prev_group_by_value or d.get('item_name'))
 		total_row['percent_gt'] = flt(total_row['total']/grand_total * 100)
 		data.append(total_row)
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 0c8957a..92a22e6 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
@@ -111,7 +111,7 @@
 
 		data.append(row)
 
-	if filters.get('group_by'):
+	if filters.get('group_by') and item_list:
 		total_row = total_row_map.get(prev_group_by_value or d.get('item_name'))
 		total_row['percent_gt'] = flt(total_row['total']/grand_total * 100)
 		data.append(total_row)
diff --git a/erpnext/accounts/report/tds_computation_summary/tds_computation_summary.py b/erpnext/accounts/report/tds_computation_summary/tds_computation_summary.py
index 2e805f8..c7cfee7 100644
--- a/erpnext/accounts/report/tds_computation_summary/tds_computation_summary.py
+++ b/erpnext/accounts/report/tds_computation_summary/tds_computation_summary.py
@@ -44,9 +44,14 @@
 	out = []
 	for supplier in filters.supplier:
 		tds = frappe.get_doc("Tax Withholding Category", supplier.tax_withholding_category)
-		rate = [d.tax_withholding_rate for d in tds.rates if d.fiscal_year == filters.fiscal_year][0]
+		rate = [d.tax_withholding_rate for d in tds.rates if d.fiscal_year == filters.fiscal_year]
+
+		if rate:
+			rate = rate[0]
+
 		try:
 			account = [d.account for d in tds.accounts if d.company == filters.company][0]
+
 		except IndexError:
 			account = []
 		total_invoiced_amount, tds_deducted = get_invoice_and_tds_amount(supplier.name, account,
@@ -76,7 +81,7 @@
 	supplier_credit_amount = flt(sum([d.credit for d in entries]))
 
 	vouchers = [d.voucher_no for d in entries]
-	vouchers += get_advance_vouchers(supplier, company=company,
+	vouchers += get_advance_vouchers([supplier], company=company,
 		from_date=from_date, to_date=to_date)
 
 	tds_deducted = 0
@@ -89,7 +94,7 @@
 		""".format(', '.join(["'%s'" % d for d in vouchers])),
 			(account, from_date, to_date, company))[0][0])
 
-	debit_note_amount = get_debit_note_amount(supplier, from_date, to_date, company=company)
+	debit_note_amount = get_debit_note_amount([supplier], from_date, to_date, company=company)
 
 	total_invoiced_amount = supplier_credit_amount + tds_deducted - debit_note_amount
 
diff --git a/erpnext/accounts/utils.py b/erpnext/accounts/utils.py
index 4789063..5165495 100644
--- a/erpnext/accounts/utils.py
+++ b/erpnext/accounts/utils.py
@@ -817,48 +817,37 @@
 		pass
 
 @frappe.whitelist()
-def update_number_field(doctype_name, name, field_name, number_value, company):
+def update_cost_center(docname, cost_center_name, cost_center_number, company):
 	'''
-		doctype_name = Name of the DocType
-		name = Docname being referred
-		field_name = Name of the field thats holding the 'number' attribute
-		number_value = Numeric value entered in field_name
-
-		Stores the number entered in the dialog to the DocType's field.
-
 		Renames the document by adding the number as a prefix to the current name and updates
 		all transaction where it was present.
 	'''
-	doc_title = frappe.db.get_value(doctype_name, name, frappe.scrub(doctype_name)+"_name")
+	validate_field_number("Cost Center", docname, cost_center_number, company, "cost_center_number")
 
-	validate_field_number(doctype_name, name, number_value, company, field_name)
+	if cost_center_number:
+		frappe.db.set_value("Cost Center", docname, "cost_center_number", cost_center_number.strip())
+	else:
+		frappe.db.set_value("Cost Center", docname, "cost_center_number", "")
 
-	frappe.db.set_value(doctype_name, name, field_name, number_value)
+	frappe.db.set_value("Cost Center", docname, "cost_center_name", cost_center_name.strip())
 
-	if doc_title[0].isdigit():
-		separator = " - " if " - " in doc_title else " "
-		doc_title = doc_title.split(separator, 1)[1]
-
-	frappe.db.set_value(doctype_name, name, frappe.scrub(doctype_name)+"_name", doc_title)
-
-	new_name = get_autoname_with_number(number_value, doc_title, name, company)
-
-	if name != new_name:
-		frappe.rename_doc(doctype_name, name, new_name)
+	new_name = get_autoname_with_number(cost_center_number, cost_center_name, docname, company)
+	if docname != new_name:
+		frappe.rename_doc("Cost Center", docname, new_name, force=1)
 		return new_name
 
-def validate_field_number(doctype_name, name, number_value, company, field_name):
+def validate_field_number(doctype_name, docname, number_value, company, field_name):
 	''' Validate if the number entered isn't already assigned to some other document. '''
 	if number_value:
+		filters = {field_name: number_value, "name": ["!=", docname]}
 		if company:
-			doctype_with_same_number = frappe.db.get_value(doctype_name,
-				{field_name: number_value, "company": company, "name": ["!=", name]})
-		else:
-			doctype_with_same_number = frappe.db.get_value(doctype_name,
-				{field_name: number_value, "name": ["!=", name]})
+			filters["company"] = company
+
+		doctype_with_same_number = frappe.db.get_value(doctype_name, filters)
+
 		if doctype_with_same_number:
-			frappe.throw(_("{0} Number {1} already used in account {2}")
-				.format(doctype_name, number_value, doctype_with_same_number))
+			frappe.throw(_("{0} Number {1} is already used in {2} {3}")
+				.format(doctype_name, number_value, doctype_name.lower(), doctype_with_same_number))
 
 def get_autoname_with_number(number_value, doc_title, name, company):
 	''' append title with prefix as number and suffix as company's abbreviation separated by '-' '''
@@ -897,4 +886,60 @@
 	return frappe.get_all("Account", filters = {
 		"account_type": "Stock",
 		"company": company
-	})
\ No newline at end of file
+	})
+
+def update_gl_entries_after(posting_date, posting_time, for_warehouses=None, for_items=None,
+		warehouse_account=None, company=None):
+	def _delete_gl_entries(voucher_type, voucher_no):
+		frappe.db.sql("""delete from `tabGL Entry`
+			where voucher_type=%s and voucher_no=%s""", (voucher_type, voucher_no))
+
+	if not warehouse_account:
+		warehouse_account = get_warehouse_account_map(company)
+
+	future_stock_vouchers = get_future_stock_vouchers(posting_date, posting_time, for_warehouses, for_items)
+	gle = get_voucherwise_gl_entries(future_stock_vouchers, posting_date)
+
+	for voucher_type, voucher_no in future_stock_vouchers:
+		existing_gle = gle.get((voucher_type, voucher_no), [])
+		voucher_obj = frappe.get_doc(voucher_type, voucher_no)
+		expected_gle = voucher_obj.get_gl_entries(warehouse_account)
+		if expected_gle:
+			if not existing_gle or not compare_existing_and_expected_gle(existing_gle, expected_gle):
+				_delete_gl_entries(voucher_type, voucher_no)
+				voucher_obj.make_gl_entries(gl_entries=expected_gle, repost_future_gle=False, from_repost=True)
+		else:
+			_delete_gl_entries(voucher_type, voucher_no)
+
+def get_future_stock_vouchers(posting_date, posting_time, for_warehouses=None, for_items=None):
+	future_stock_vouchers = []
+
+	values = []
+	condition = ""
+	if for_items:
+		condition += " and item_code in ({})".format(", ".join(["%s"] * len(for_items)))
+		values += for_items
+
+	if for_warehouses:
+		condition += " and warehouse in ({})".format(", ".join(["%s"] * len(for_warehouses)))
+		values += for_warehouses
+
+	for d in frappe.db.sql("""select distinct sle.voucher_type, sle.voucher_no
+		from `tabStock Ledger Entry` sle
+		where timestamp(sle.posting_date, sle.posting_time) >= timestamp(%s, %s) {condition}
+		order by timestamp(sle.posting_date, sle.posting_time) asc, creation asc for update""".format(condition=condition),
+		tuple([posting_date, posting_time] + values), as_dict=True):
+			future_stock_vouchers.append([d.voucher_type, d.voucher_no])
+
+	return future_stock_vouchers
+
+def get_voucherwise_gl_entries(future_stock_vouchers, posting_date):
+	gl_entries = {}
+	if future_stock_vouchers:
+		for d in frappe.db.sql("""select * from `tabGL Entry`
+			where posting_date >= %s and voucher_no in (%s)""" %
+			('%s', ', '.join(['%s']*len(future_stock_vouchers))),
+			tuple([posting_date] + [d[1] for d in future_stock_vouchers]), as_dict=1):
+				gl_entries.setdefault((d.voucher_type, d.voucher_no), []).append(d)
+
+	return gl_entries
\ No newline at end of file
diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py
index 759d42a..06dfa19 100644
--- a/erpnext/assets/doctype/asset/asset.py
+++ b/erpnext/assets/doctype/asset/asset.py
@@ -11,7 +11,7 @@
 from erpnext.assets.doctype.asset_category.asset_category import get_asset_category_account
 from erpnext.assets.doctype.asset.depreciation \
 	import get_disposal_account_and_cost_center, get_depreciation_accounts
-from erpnext.accounts.general_ledger import make_gl_entries, delete_gl_entries
+from erpnext.accounts.general_ledger import make_gl_entries, make_reverse_gl_entries
 from erpnext.accounts.utils import get_account_currency
 from erpnext.controllers.accounts_controller import AccountsController
 
@@ -22,6 +22,7 @@
 		self.validate_item()
 		self.set_missing_values()
 		self.prepare_depreciation_data()
+		self.validate_gross_and_purchase_amount()
 		if self.get("schedules"):
 			self.validate_expected_value_after_useful_life()
 
@@ -41,7 +42,8 @@
 		self.validate_cancellation()
 		self.delete_depreciation_entries()
 		self.set_status()
-		delete_gl_entries(voucher_type='Asset', voucher_no=self.name)
+		self.ignore_linked_doctypes = ('GL Entry', 'Stock Ledger Entry')
+		make_reverse_gl_entries(voucher_type='Asset', voucher_no=self.name)
 		self.db_set('booked_fixed_asset', 0)
 
 	def validate_asset_and_reference(self):
@@ -123,6 +125,12 @@
 
 		if self.available_for_use_date and getdate(self.available_for_use_date) < getdate(self.purchase_date):
 			frappe.throw(_("Available-for-use Date should be after purchase date"))
+	
+	def validate_gross_and_purchase_amount(self):
+		if self.gross_purchase_amount and self.gross_purchase_amount != self.purchase_receipt_amount:
+			frappe.throw(_("Gross Purchase Amount should be {} to purchase amount of one single Asset. {}\
+				Please do not book expense of multiple assets against one single Asset.")
+				.format(frappe.bold("equal"), "<br>"), title=_("Invalid Gross Purchase Amount"))
 
 	def cancel_auto_gen_movement(self):
 		movements = frappe.db.sql(
diff --git a/erpnext/assets/doctype/asset/test_asset.py b/erpnext/assets/doctype/asset/test_asset.py
index a56440d..a0f8d15 100644
--- a/erpnext/assets/doctype/asset/test_asset.py
+++ b/erpnext/assets/doctype/asset/test_asset.py
@@ -66,9 +66,6 @@
 		pr.cancel()
 		self.assertEqual(asset.docstatus, 2)
 
-		self.assertFalse(frappe.db.get_value("GL Entry",
-			{"voucher_type": "Purchase Invoice", "voucher_no": pi.name}))
-
 	def test_is_fixed_asset_set(self):
 		asset = create_asset(is_existing_asset = 1)
 		doc = frappe.new_doc('Purchase Invoice')
@@ -82,7 +79,6 @@
 		doc.set_missing_values()
 		self.assertEquals(doc.items[0].is_fixed_asset, 1)
 
-
 	def test_schedule_for_straight_line_method(self):
 		pr = make_purchase_receipt(item_code="Macbook Pro",
 			qty=1, rate=100000.0, location="Test Location")
@@ -599,6 +595,7 @@
 		"purchase_date": "2015-01-01",
 		"calculate_depreciation": 0,
 		"gross_purchase_amount": 100000,
+		"purchase_receipt_amount": 100000,
 		"expected_value_after_useful_life": 10000,
 		"warehouse": args.warehouse or "_Test Warehouse - _TC",
 		"available_for_use_date": "2020-06-06",
diff --git a/erpnext/assets/doctype/asset_category/asset_category.py b/erpnext/assets/doctype/asset_category/asset_category.py
index 9bf4df4..9a33fc1 100644
--- a/erpnext/assets/doctype/asset_category/asset_category.py
+++ b/erpnext/assets/doctype/asset_category/asset_category.py
@@ -11,7 +11,8 @@
 class AssetCategory(Document):
 	def validate(self):
 		self.validate_finance_books()
-		self.validate_accounts()
+		self.validate_account_types()
+		self.validate_account_currency()
 
 	def validate_finance_books(self):
 		for d in self.finance_books:
@@ -19,7 +20,26 @@
 				if cint(d.get(frappe.scrub(field)))<1:
 					frappe.throw(_("Row {0}: {1} must be greater than 0").format(d.idx, field), frappe.MandatoryError)
 	
-	def validate_accounts(self):
+	def validate_account_currency(self):
+		account_types = [
+			'fixed_asset_account', 'accumulated_depreciation_account', 'depreciation_expense_account', 'capital_work_in_progress_account'
+		]
+		invalid_accounts = []
+		for d in self.accounts:
+			company_currency = frappe.get_value('Company', d.get('company_name'), 'default_currency')
+			for type_of_account in account_types:
+				if d.get(type_of_account):
+					account_currency = frappe.get_value("Account", d.get(type_of_account), "account_currency")
+					if account_currency != company_currency:
+						invalid_accounts.append(frappe._dict({ 'type': type_of_account, 'idx': d.idx, 'account': d.get(type_of_account) }))
+	
+		for d in invalid_accounts:
+			frappe.throw(_("Row #{}: Currency of {} - {} doesn't matches company currency.")
+				.format(d.idx, frappe.bold(frappe.unscrub(d.type)), frappe.bold(d.account)),
+				title=_("Invalid Account"))
+
+	
+	def validate_account_types(self):
 		account_type_map = {
 			'fixed_asset_account': { 'account_type': 'Fixed Asset' },
 			'accumulated_depreciation_account': { 'account_type': 'Accumulated Depreciation' },
diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.js b/erpnext/buying/doctype/purchase_order/purchase_order.js
index 3111a3a..4a8146a 100644
--- a/erpnext/buying/doctype/purchase_order/purchase_order.js
+++ b/erpnext/buying/doctype/purchase_order/purchase_order.js
@@ -27,15 +27,6 @@
 		frm.set_indicator_formatter('item_code',
 			function(doc) { return (doc.qty<=doc.received_qty) ? "green" : "orange" })
 
-		frm.set_query("blanket_order", "items", function() {
-			return {
-				filters: {
-					"company": frm.doc.company,
-					"docstatus": 1
-				}
-			}
-		});
-
 		frm.set_query("expense_account", "items", function() {
 			return {
 				query: "erpnext.controllers.queries.get_expense_account",
@@ -365,9 +356,7 @@
 					method: "erpnext.stock.doctype.material_request.material_request.make_purchase_order",
 					source_doctype: "Material Request",
 					target: me.frm,
-					setters: {
-						company: me.frm.doc.company
-					},
+					setters: {},
 					get_query_filters: {
 						material_request_type: "Purchase",
 						docstatus: 1,
@@ -384,7 +373,7 @@
 					source_doctype: "Supplier Quotation",
 					target: me.frm,
 					setters: {
-						company: me.frm.doc.company
+						supplier: me.frm.doc.supplier
 					},
 					get_query_filters: {
 						docstatus: 1,
diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.json b/erpnext/buying/doctype/purchase_order/purchase_order.json
index 578858c..a4f60fb 100644
--- a/erpnext/buying/doctype/purchase_order/purchase_order.json
+++ b/erpnext/buying/doctype/purchase_order/purchase_order.json
@@ -54,11 +54,6 @@
   "items_section",
   "scan_barcode",
   "items",
-  "section_break_48",
-  "pricing_rules",
-  "raw_material_details",
-  "set_reserve_warehouse",
-  "supplied_items",
   "sb_last_purchase",
   "total_qty",
   "base_total",
@@ -67,6 +62,11 @@
   "total_net_weight",
   "total",
   "net_total",
+  "section_break_48",
+  "pricing_rules",
+  "raw_material_details",
+  "set_reserve_warehouse",
+  "supplied_items",
   "taxes_section",
   "tax_category",
   "column_break_50",
@@ -105,23 +105,25 @@
   "payment_schedule_section",
   "payment_terms_template",
   "payment_schedule",
+  "tracking_section",
+  "per_billed",
+  "column_break_75",
+  "per_received",
   "terms_section_break",
   "tc_name",
   "terms",
   "more_info",
   "status",
   "ref_sq",
+  "column_break_74",
   "party_account_currency",
   "inter_company_order_reference",
-  "column_break_74",
-  "per_received",
-  "per_billed",
   "column_break5",
   "letter_head",
   "select_print_heading",
   "column_break_86",
-  "group_same_items",
   "language",
+  "group_same_items",
   "subscription_section",
   "from_date",
   "to_date",
@@ -220,7 +222,7 @@
    "allow_on_submit": 1,
    "fieldname": "schedule_date",
    "fieldtype": "Date",
-   "label": "Reqd By Date"
+   "label": "Required By"
   },
   {
    "allow_on_submit": 1,
@@ -432,6 +434,7 @@
    "fieldtype": "Section Break"
   },
   {
+   "description": "Sets 'Warehouse' in each row of the Items table.",
    "fieldname": "set_warehouse",
    "fieldtype": "Link",
    "label": "Set Target Warehouse",
@@ -827,6 +830,7 @@
    "read_only": 1
   },
   {
+   "collapsible": 1,
    "fieldname": "payment_schedule_section",
    "fieldtype": "Section Break",
    "label": "Payment Terms"
@@ -917,7 +921,8 @@
    "fieldname": "inter_company_order_reference",
    "fieldtype": "Link",
    "label": "Inter Company Order Reference",
-   "options": "Sales Order"
+   "options": "Sales Order",
+   "read_only": 1
   },
   {
    "fieldname": "column_break_74",
@@ -930,8 +935,6 @@
    "in_list_view": 1,
    "label": "% Received",
    "no_copy": 1,
-   "oldfieldname": "per_received",
-   "oldfieldtype": "Currency",
    "print_hide": 1,
    "read_only": 1
   },
@@ -942,8 +945,6 @@
    "in_list_view": 1,
    "label": "% Billed",
    "no_copy": 1,
-   "oldfieldname": "per_billed",
-   "oldfieldtype": "Currency",
    "print_hide": 1,
    "read_only": 1
   },
@@ -998,6 +999,7 @@
    "print_hide": 1
   },
   {
+   "collapsible": 1,
    "fieldname": "subscription_section",
    "fieldtype": "Section Break",
    "label": "Subscription Section"
@@ -1050,13 +1052,23 @@
    "fieldtype": "Link",
    "label": "Set Reserve Warehouse",
    "options": "Warehouse"
+  },
+  {
+   "collapsible": 1,
+   "fieldname": "tracking_section",
+   "fieldtype": "Section Break",
+   "label": "Tracking"
+  },
+  {
+   "fieldname": "column_break_75",
+   "fieldtype": "Column Break"
   }
  ],
  "icon": "fa fa-file-text",
  "idx": 105,
  "is_submittable": 1,
  "links": [],
- "modified": "2020-04-17 13:04:28.185197",
+ "modified": "2020-04-24 12:13:14.186280",
  "modified_by": "Administrator",
  "module": "Buying",
  "name": "Purchase Order",
diff --git a/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json b/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json
index e37e1dd..7a52c28 100644
--- a/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json
+++ b/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json
@@ -18,10 +18,6 @@
   "col_break1",
   "image",
   "image_view",
-  "manufacture_details",
-  "manufacturer",
-  "column_break_14",
-  "manufacturer_part_no",
   "quantity_and_rate",
   "qty",
   "stock_uom",
@@ -44,7 +40,6 @@
   "base_amount",
   "pricing_rules",
   "is_free_item",
-  "is_fixed_asset",
   "section_break_29",
   "net_rate",
   "net_amount",
@@ -52,11 +47,6 @@
   "base_net_rate",
   "base_net_amount",
   "billed_amt",
-  "item_weight_details",
-  "weight_per_unit",
-  "total_weight",
-  "column_break_40",
-  "weight_uom",
   "warehouse_and_reference",
   "warehouse",
   "delivered_by_supplier",
@@ -80,20 +70,31 @@
   "column_break_60",
   "received_qty",
   "returned_qty",
+  "manufacture_details",
+  "manufacturer",
+  "column_break_14",
+  "manufacturer_part_no",
+  "more_info_section_break",
+  "is_fixed_asset",
+  "item_tax_rate",
   "accounting_details",
   "expense_account",
   "column_break_68",
+  "item_weight_details",
+  "weight_per_unit",
+  "total_weight",
+  "column_break_40",
+  "weight_uom",
   "accounting_dimensions_section",
   "cost_center",
   "dimension_col_break",
   "section_break_72",
-  "page_break",
-  "item_tax_rate"
+  "page_break"
  ],
  "fields": [
   {
    "bold": 1,
-   "columns": 3,
+   "columns": 2,
    "fieldname": "item_code",
    "fieldtype": "Link",
    "in_list_view": 1,
@@ -133,7 +134,7 @@
    "fieldname": "schedule_date",
    "fieldtype": "Date",
    "in_list_view": 1,
-   "label": "Reqd By Date",
+   "label": "Required By",
    "oldfieldname": "schedule_date",
    "oldfieldtype": "Date",
    "print_hide": 1,
@@ -216,15 +217,16 @@
    "print_hide": 1
   },
   {
+   "columns": 1,
    "fieldname": "uom",
    "fieldtype": "Link",
+   "in_list_view": 1,
    "label": "UOM",
    "oldfieldname": "uom",
    "oldfieldtype": "Link",
    "options": "UOM",
    "print_width": "100px",
-   "reqd": 1,
-   "width": "100px"
+   "reqd": 1
   },
   {
    "fieldname": "conversion_factor",
@@ -685,6 +687,7 @@
    "fieldtype": "Column Break"
   },
   {
+   "collapsible": 1,
    "fieldname": "manufacture_details",
    "fieldtype": "Section Break",
    "label": "Manufacture"
@@ -717,12 +720,17 @@
    "fieldtype": "Check",
    "label": "Is Fixed Asset",
    "read_only": 1
+  },
+  {
+   "fieldname": "more_info_section_break",
+   "fieldtype": "Section Break",
+   "label": "More Information"
   }
  ],
  "idx": 1,
  "istable": 1,
  "links": [],
- "modified": "2020-04-07 18:35:17.558928",
+ "modified": "2020-04-21 11:55:58.643393",
  "modified_by": "Administrator",
  "module": "Buying",
  "name": "Purchase Order Item",
diff --git a/erpnext/buying/doctype/purchase_order_item_supplied/purchase_order_item_supplied.json b/erpnext/buying/doctype/purchase_order_item_supplied/purchase_order_item_supplied.json
index 8435bbb..c3e1bf5 100644
--- a/erpnext/buying/doctype/purchase_order_item_supplied/purchase_order_item_supplied.json
+++ b/erpnext/buying/doctype/purchase_order_item_supplied/purchase_order_item_supplied.json
@@ -1,20 +1,26 @@
 {
+ "actions": [],
  "creation": "2013-02-22 01:27:42",
  "doctype": "DocType",
  "editable_grid": 1,
+ "engine": "InnoDB",
  "field_order": [
   "main_item_code",
-  "rm_item_code",
-  "required_qty",
-  "supplied_qty",
-  "rate",
-  "amount",
-  "column_break_6",
   "bom_detail_no",
-  "reference_name",
-  "conversion_factor",
   "stock_uom",
-  "reserve_warehouse"
+  "conversion_factor",
+  "column_break_6",
+  "rm_item_code",
+  "reference_name",
+  "reserve_warehouse",
+  "section_break2",
+  "rate",
+  "col_break2",
+  "amount",
+  "section_break1",
+  "required_qty",
+  "col_break1",
+  "supplied_qty"
  ],
  "fields": [
   {
@@ -120,15 +126,34 @@
    "in_list_view": 1,
    "label": "Supplied Qty",
    "read_only": 1
+  },
+  {
+   "fieldname": "section_break1",
+   "fieldtype": "Section Break"
+  },
+  {
+   "fieldname": "col_break1",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "section_break2",
+   "fieldtype": "Section Break"
+  },
+  {
+   "fieldname": "col_break2",
+   "fieldtype": "Column Break"
   }
  ],
  "hide_toolbar": 1,
  "idx": 1,
  "istable": 1,
- "modified": "2019-08-20 13:37:32.702068",
+ "links": [],
+ "modified": "2020-03-12 15:43:53.862897",
  "modified_by": "Administrator",
  "module": "Buying",
  "name": "Purchase Order Item Supplied",
  "owner": "dhanalekshmi@webnotestech.com",
- "permissions": []
+ "permissions": [],
+ "sort_field": "modified",
+ "sort_order": "DESC"
 }
\ No newline at end of file
diff --git a/erpnext/buying/doctype/supplier/supplier_dashboard.py b/erpnext/buying/doctype/supplier/supplier_dashboard.py
index d0d5b73..1625103 100644
--- a/erpnext/buying/doctype/supplier/supplier_dashboard.py
+++ b/erpnext/buying/doctype/supplier/supplier_dashboard.py
@@ -23,15 +23,11 @@
 			},
 			{
 				'label': _('Payments'),
-				'items': ['Payment Entry']
-			},
-			{
-				'label': _('Bank'),
-				'items': ['Bank Account']
+				'items': ['Payment Entry', 'Bank Account']
 			},
 			{
 				'label': _('Pricing'),
 				'items': ['Pricing Rule']
 			}
 		]
-	}
\ No newline at end of file
+	}
diff --git a/erpnext/buying/report/procurement_tracker/procurement_tracker.py b/erpnext/buying/report/procurement_tracker/procurement_tracker.py
index 866bf0c..3966879 100644
--- a/erpnext/buying/report/procurement_tracker/procurement_tracker.py
+++ b/erpnext/buying/report/procurement_tracker/procurement_tracker.py
@@ -141,19 +141,18 @@
 	conditions = ""
 
 	if filters.get("company"):
-		conditions += " AND company=%s"% frappe.db.escape(filters.get('company'))
+		conditions += " AND par.company=%s" % frappe.db.escape(filters.get('company'))
 
 	if filters.get("cost_center") or filters.get("project"):
 		conditions += """
-			AND (cost_center=%s
-			OR project=%s)
-			"""% (frappe.db.escape(filters.get('cost_center')), frappe.db.escape(filters.get('project')))
+			AND (child.`cost_center`=%s OR child.`project`=%s)
+			""" % (frappe.db.escape(filters.get('cost_center')), frappe.db.escape(filters.get('project')))
 
 	if filters.get("from_date"):
-		conditions += " AND transaction_date>=%s"% filters.get('from_date')
+		conditions += " AND par.transaction_date>='%s'" % filters.get('from_date')
 
 	if filters.get("to_date"):
-		conditions += " AND transaction_date<=%s"% filters.get('to_date')
+		conditions += " AND par.transaction_date<='%s'" % filters.get('to_date')
 	return conditions
 
 def get_data(filters):
@@ -162,7 +161,6 @@
 	mr_records, procurement_record_against_mr = get_mapped_mr_details(conditions)
 	pr_records = get_mapped_pr_records()
 	pi_records = get_mapped_pi_records()
-	print(pi_records)
 
 	procurement_record=[]
 	if procurement_record_against_mr:
@@ -198,16 +196,16 @@
 	mr_records = {}
 	mr_details = frappe.db.sql("""
 		SELECT
-			mr.transaction_date,
-			mr.per_ordered,
-			mr_item.name,
-			mr_item.parent,
-			mr_item.amount
-		FROM `tabMaterial Request` mr, `tabMaterial Request Item` mr_item
+			par.transaction_date,
+			par.per_ordered,
+			child.name,
+			child.parent,
+			child.amount
+		FROM `tabMaterial Request` par, `tabMaterial Request Item` child
 		WHERE
-			mr.per_ordered>=0
-			AND mr.name=mr_item.parent
-			AND mr.docstatus=1
+			par.per_ordered>=0
+			AND par.name=child.parent
+			AND par.docstatus=1
 			{conditions}
 		""".format(conditions=conditions), as_dict=1) #nosec
 
@@ -254,29 +252,29 @@
 def get_po_entries(conditions):
 	return frappe.db.sql("""
 		SELECT
-			po_item.name,
-			po_item.parent,
-			po_item.cost_center,
-			po_item.project,
-			po_item.warehouse,
-			po_item.material_request,
-			po_item.material_request_item,
-			po_item.description,
-			po_item.stock_uom,
-			po_item.qty,
-			po_item.amount,
-			po_item.base_amount,
-			po_item.schedule_date,
-			po.transaction_date,
-			po.supplier,
-			po.status,
-			po.owner
-		FROM `tabPurchase Order` po, `tabPurchase Order Item` po_item
+			child.name,
+			child.parent,
+			child.cost_center,
+			child.project,
+			child.warehouse,
+			child.material_request,
+			child.material_request_item,
+			child.description,
+			child.stock_uom,
+			child.qty,
+			child.amount,
+			child.base_amount,
+			child.schedule_date,
+			par.transaction_date,
+			par.supplier,
+			par.status,
+			par.owner
+		FROM `tabPurchase Order` par, `tabPurchase Order Item` child
 		WHERE
-			po.docstatus = 1
-			AND po.name = po_item.parent
-			AND po.status not in  ("Closed","Completed","Cancelled")
+			par.docstatus = 1
+			AND par.name = child.parent
+			AND par.status not in  ("Closed","Completed","Cancelled")
 			{conditions}
 		GROUP BY
-			po.name,po_item.item_code
+			par.name, child.item_code
 		""".format(conditions=conditions), as_dict=1) #nosec
\ No newline at end of file
diff --git a/erpnext/config/accounts.py b/erpnext/config/accounts.py
index 08711fc..839c4ad 100644
--- a/erpnext/config/accounts.py
+++ b/erpnext/config/accounts.py
@@ -183,8 +183,8 @@
 				},
 				{
 					"type": "doctype",
-					"label": _("Update Bank Transaction Dates"),
-					"name": "Bank Reconciliation",
+					"label": _("Update Bank Clearance Dates"),
+					"name": "Bank Clearance",
 					"description": _("Update bank payment dates with journals.")
 				},
 				{
@@ -245,6 +245,10 @@
 					"name": "Supplier Ledger Summary",
 					"doctype": "Sales Invoice",
 					"is_query_report": True,
+				},
+				{
+					"type": "doctype",
+					"name": "Process Deferred Accounting"
 				}
 			]
 		},
diff --git a/erpnext/config/hr.py b/erpnext/config/hr.py
index 7b3b466..9855a11 100644
--- a/erpnext/config/hr.py
+++ b/erpnext/config/hr.py
@@ -172,6 +172,10 @@
 				},
 				{
 					"type": "doctype",
+					"name": "Income Tax Slab",
+				},
+				{
+					"type": "doctype",
 					"name": "Salary Component",
 				},
 				{
@@ -211,6 +215,10 @@
 				},
 				{
 					"type": "doctype",
+					"name": "Employee Other Income",
+				},
+				{
+					"type": "doctype",
 					"name": "Employee Benefit Application",
 					"dependencies": ["Employee"]
 				},
diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py
index 4045250..eecb143 100644
--- a/erpnext/controllers/accounts_controller.py
+++ b/erpnext/controllers/accounts_controller.py
@@ -664,23 +664,26 @@
 	def set_total_advance_paid(self):
 		if self.doctype == "Sales Order":
 			dr_or_cr = "credit_in_account_currency"
+			rev_dr_or_cr = "debit_in_account_currency"
 			party = self.customer
 		else:
 			dr_or_cr = "debit_in_account_currency"
+			rev_dr_or_cr = "credit_in_account_currency"
 			party = self.supplier
 
 		advance = frappe.db.sql("""
 			select
-				account_currency, sum({dr_or_cr}) as amount
+				account_currency, sum({dr_or_cr}) - sum({rev_dr_cr}) as amount
 			from
 				`tabGL Entry`
 			where
 				against_voucher_type = %s and against_voucher = %s and party=%s
 				and docstatus = 1
-		""".format(dr_or_cr=dr_or_cr), (self.doctype, self.name, party), as_dict=1)
+		""".format(dr_or_cr=dr_or_cr, rev_dr_cr=rev_dr_or_cr), (self.doctype, self.name, party), as_dict=1) #nosec
 
 		if advance:
 			advance = advance[0]
+
 			advance_paid = flt(advance.amount, self.precision("advance_paid"))
 			formatted_advance_paid = fmt_money(advance_paid, precision=self.precision("advance_paid"),
 											   currency=advance.account_currency)
@@ -819,7 +822,7 @@
 		else:
 			for d in self.get("payment_schedule"):
 				if d.invoice_portion:
-					d.payment_amount = grand_total * flt(d.invoice_portion) / 100
+					d.payment_amount = flt(grand_total * flt(d.invoice_portion) / 100, d.precision('payment_amount'))
 
 	def set_due_date(self):
 		due_dates = [d.due_date for d in self.get("payment_schedule") if d.due_date]
diff --git a/erpnext/controllers/buying_controller.py b/erpnext/controllers/buying_controller.py
index 0e72ec2..608e537 100644
--- a/erpnext/controllers/buying_controller.py
+++ b/erpnext/controllers/buying_controller.py
@@ -101,7 +101,7 @@
 				for d in tax_for_valuation:
 					d.category = 'Total'
 				msgprint(_('Tax Category has been changed to "Total" because all the Items are non-stock items'))
-	
+
 	def validate_asset_return(self):
 		if self.doctype not in ['Purchase Receipt', 'Purchase Invoice'] or not self.is_return:
 			return
@@ -691,10 +691,10 @@
 						for qty in range(cint(d.qty)):
 							asset = self.make_asset(d)
 							created_assets.append(asset)
-						
+
 						if len(created_assets) > 5:
 							# dont show asset form links if more than 5 assets are created
-							messages.append(_('{} Asset{} created for {}').format(len(created_assets), is_plural, frappe.bold(d.item_code)))
+							messages.append(_('{} Assets created for {}').format(len(created_assets), frappe.bold(d.item_code)))
 						else:
 							assets_link = list(map(lambda d: frappe.utils.get_link_to_form('Asset', d), created_assets))
 							assets_link = frappe.bold(','.join(assets_link))
diff --git a/erpnext/controllers/queries.py b/erpnext/controllers/queries.py
index c14bb66..5febfd6 100644
--- a/erpnext/controllers/queries.py
+++ b/erpnext/controllers/queries.py
@@ -371,6 +371,19 @@
 		fields = ["name", "parent_account"],
 		limit_start=start, limit_page_length=page_len, as_list=True)
 
+def get_blanket_orders(doctype, txt, searchfield, start, page_len, filters):
+	return frappe.db.sql("""select distinct bo.name, bo.blanket_order_type, bo.to_date
+		from `tabBlanket Order` bo, `tabBlanket Order Item` boi
+		where
+			boi.parent = bo.name
+			and boi.item_code = {item_code}
+			and bo.blanket_order_type = '{blanket_order_type}'
+			and bo.company = {company}
+			and bo.docstatus = 1"""
+		.format(item_code = frappe.db.escape(filters.get("item")),
+			blanket_order_type = filters.get("blanket_order_type"),
+			company = frappe.db.escape(filters.get("company"))
+		))
 
 @frappe.whitelist()
 def get_income_account(doctype, txt, searchfield, start, page_len, filters):
diff --git a/erpnext/controllers/selling_controller.py b/erpnext/controllers/selling_controller.py
index 2b21ee8..90ba8b3 100644
--- a/erpnext/controllers/selling_controller.py
+++ b/erpnext/controllers/selling_controller.py
@@ -46,6 +46,7 @@
 		set_default_income_account_for_item(self)
 		self.set_customer_address()
 		self.validate_for_duplicate_items()
+		self.validate_target_warehouse()
 
 	def set_missing_values(self, for_validate=False):
 
@@ -403,6 +404,14 @@
 				else:
 					chk_dupl_itm.append(f)
 
+	def validate_target_warehouse(self):
+		items = self.get("items") + (self.get("packed_items") or [])
+
+		for d in items:
+			if d.get("target_warehouse") and d.get("warehouse") == d.get("target_warehouse"):
+				warehouse = frappe.bold(d.get("target_warehouse"))
+				frappe.throw(_("Row {0}: Delivery Warehouse ({1}) and Customer Warehouse ({2}) can not be same")
+					.format(d.idx, warehouse, warehouse))
 
 	def validate_items(self):
 		# validate items to see if they have is_sales_item enabled
diff --git a/erpnext/controllers/stock_controller.py b/erpnext/controllers/stock_controller.py
index 55a2c43..86de808 100644
--- a/erpnext/controllers/stock_controller.py
+++ b/erpnext/controllers/stock_controller.py
@@ -3,11 +3,11 @@
 
 from __future__ import unicode_literals
 import frappe, erpnext
-from frappe.utils import cint, flt, cstr
+from frappe.utils import cint, flt, cstr, get_link_to_form, today, getdate
 from frappe import _
 import frappe.defaults
 from erpnext.accounts.utils import get_fiscal_year
-from erpnext.accounts.general_ledger import make_gl_entries, delete_gl_entries, process_gl_map
+from erpnext.accounts.general_ledger import make_gl_entries, make_reverse_gl_entries, process_gl_map
 from erpnext.controllers.accounts_controller import AccountsController
 from erpnext.stock.stock_ledger import get_valuation_rate
 from erpnext.stock import get_warehouse_account_map
@@ -23,9 +23,9 @@
 		self.validate_serialized_batch()
 		self.validate_customer_provided_item()
 
-	def make_gl_entries(self, gl_entries=None, repost_future_gle=True, from_repost=False):
+	def make_gl_entries(self, gl_entries=None):
 		if self.docstatus == 2:
-			delete_gl_entries(voucher_type=self.doctype, voucher_no=self.name)
+			make_reverse_gl_entries(voucher_type=self.doctype, voucher_no=self.name)
 
 		if cint(erpnext.is_perpetual_inventory_enabled(self.company)):
 			warehouse_account = get_warehouse_account_map(self.company)
@@ -33,16 +33,12 @@
 			if self.docstatus==1:
 				if not gl_entries:
 					gl_entries = self.get_gl_entries(warehouse_account)
-				make_gl_entries(gl_entries, from_repost=from_repost)
+				make_gl_entries(gl_entries)
 
-			if (repost_future_gle or self.flags.repost_future_gle):
-				items, warehouses = self.get_items_and_warehouses()
-				update_gl_entries_after(self.posting_date, self.posting_time, warehouses, items,
-					warehouse_account, company=self.company)
 		elif self.doctype in ['Purchase Receipt', 'Purchase Invoice'] and self.docstatus == 1:
 			gl_entries = []
 			gl_entries = self.get_asset_gl_entry(gl_entries)
-			make_gl_entries(gl_entries, from_repost=from_repost)
+			make_gl_entries(gl_entries)
 
 	def validate_serialized_batch(self):
 		from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos
@@ -55,6 +51,13 @@
 						frappe.throw(_("Row #{0}: Serial No {1} does not belong to Batch {2}")
 							.format(d.idx, serial_no_data.name, d.batch_no))
 
+			if d.qty > 0 and d.get("batch_no") and self.get("posting_date") and self.docstatus < 2:
+				expiry_date = frappe.get_cached_value("Batch", d.get("batch_no"), "expiry_date")
+
+				if expiry_date and getdate(expiry_date) < getdate(self.posting_date):
+					frappe.throw(_("Row #{0}: The batch {1} has already expired.")
+						.format(d.idx, get_link_to_form("Batch", d.get("batch_no"))))
+
 	def get_gl_entries(self, warehouse_account=None, default_expense_account=None,
 			default_cost_center=None):
 
@@ -267,21 +270,21 @@
 			"batch_no": cstr(d.get("batch_no")).strip(),
 			"serial_no": d.get("serial_no"),
 			"project": d.get("project") or self.get('project'),
-			"is_cancelled": self.docstatus==2 and "Yes" or "No"
+			"is_cancelled": 1 if self.docstatus==2 else 0
 		})
 
 		sl_dict.update(args)
 		return sl_dict
 
-	def make_sl_entries(self, sl_entries, is_amended=None, allow_negative_stock=False,
+	def make_sl_entries(self, sl_entries, allow_negative_stock=False,
 			via_landed_cost_voucher=False):
 		from erpnext.stock.stock_ledger import make_sl_entries
-		make_sl_entries(sl_entries, is_amended, allow_negative_stock, via_landed_cost_voucher)
+		make_sl_entries(sl_entries, allow_negative_stock, via_landed_cost_voucher)
 
-	def make_gl_entries_on_cancel(self, repost_future_gle=True):
+	def make_gl_entries_on_cancel(self):
 		if frappe.db.sql("""select name from `tabGL Entry` where voucher_type=%s
 			and voucher_no=%s""", (self.doctype, self.name)):
-				self.make_gl_entries(repost_future_gle=repost_future_gle)
+				self.make_gl_entries()
 
 	def get_serialized_items(self):
 		serialized_items = []
@@ -384,29 +387,6 @@
 			if frappe.db.get_value('Item', d.item_code, 'is_customer_provided_item'):
 				d.allow_zero_valuation_rate = 1
 
-def update_gl_entries_after(posting_date, posting_time, for_warehouses=None, for_items=None,
-		warehouse_account=None, company=None):
-	def _delete_gl_entries(voucher_type, voucher_no):
-		frappe.db.sql("""delete from `tabGL Entry`
-			where voucher_type=%s and voucher_no=%s""", (voucher_type, voucher_no))
-
-	if not warehouse_account:
-		warehouse_account = get_warehouse_account_map(company)
-
-	future_stock_vouchers = get_future_stock_vouchers(posting_date, posting_time, for_warehouses, for_items)
-	gle = get_voucherwise_gl_entries(future_stock_vouchers, posting_date)
-
-	for voucher_type, voucher_no in future_stock_vouchers:
-		existing_gle = gle.get((voucher_type, voucher_no), [])
-		voucher_obj = frappe.get_doc(voucher_type, voucher_no)
-		expected_gle = voucher_obj.get_gl_entries(warehouse_account)
-		if expected_gle:
-			if not existing_gle or not compare_existing_and_expected_gle(existing_gle, expected_gle):
-				_delete_gl_entries(voucher_type, voucher_no)
-				voucher_obj.make_gl_entries(gl_entries=expected_gle, repost_future_gle=False, from_repost=True)
-		else:
-			_delete_gl_entries(voucher_type, voucher_no)
-
 def compare_existing_and_expected_gle(existing_gle, expected_gle):
 	matched = True
 	for entry in expected_gle:
@@ -423,36 +403,3 @@
 			matched = False
 			break
 	return matched
-
-def get_future_stock_vouchers(posting_date, posting_time, for_warehouses=None, for_items=None):
-	future_stock_vouchers = []
-
-	values = []
-	condition = ""
-	if for_items:
-		condition += " and item_code in ({})".format(", ".join(["%s"] * len(for_items)))
-		values += for_items
-
-	if for_warehouses:
-		condition += " and warehouse in ({})".format(", ".join(["%s"] * len(for_warehouses)))
-		values += for_warehouses
-
-	for d in frappe.db.sql("""select distinct sle.voucher_type, sle.voucher_no
-		from `tabStock Ledger Entry` sle
-		where timestamp(sle.posting_date, sle.posting_time) >= timestamp(%s, %s) {condition}
-		order by timestamp(sle.posting_date, sle.posting_time) asc, creation asc for update""".format(condition=condition),
-		tuple([posting_date, posting_time] + values), as_dict=True):
-			future_stock_vouchers.append([d.voucher_type, d.voucher_no])
-
-	return future_stock_vouchers
-
-def get_voucherwise_gl_entries(future_stock_vouchers, posting_date):
-	gl_entries = {}
-	if future_stock_vouchers:
-		for d in frappe.db.sql("""select * from `tabGL Entry`
-			where posting_date >= %s and voucher_no in (%s)""" %
-			('%s', ', '.join(['%s']*len(future_stock_vouchers))),
-			tuple([posting_date] + [d[1] for d in future_stock_vouchers]), as_dict=1):
-				gl_entries.setdefault((d.voucher_type, d.voucher_no), []).append(d)
-
-	return gl_entries
diff --git a/erpnext/crm/desk_page/crm/crm.json b/erpnext/crm/desk_page/crm/crm.json
index 4a599fe..ca13d6a 100644
--- a/erpnext/crm/desk_page/crm/crm.json
+++ b/erpnext/crm/desk_page/crm/crm.json
@@ -12,13 +12,18 @@
   },
   {
    "hidden": 0,
-   "label": "Settings",
-   "links": "[\n    {\n        \"description\": \"Manage Customer Group Tree.\",\n        \"icon\": \"fa fa-sitemap\",\n        \"label\": \"Customer Group\",\n        \"link\": \"Tree/Customer Group\",\n        \"name\": \"Customer Group\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n    },\n    {\n        \"description\": \"Manage Territory Tree.\",\n        \"icon\": \"fa fa-sitemap\",\n        \"label\": \"Territory\",\n        \"link\": \"Tree/Territory\",\n        \"name\": \"Territory\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n    },\n    {\n        \"description\": \"Manage Sales Person Tree.\",\n        \"icon\": \"fa fa-sitemap\",\n        \"label\": \"Sales Person\",\n        \"link\": \"Tree/Sales Person\",\n        \"name\": \"Sales Person\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n    },\n    {\n        \"description\": \"Sales campaigns.\",\n        \"label\": \"Campaign\",\n        \"name\": \"Campaign\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"description\": \"Sends Mails to lead or contact based on a Campaign schedule\",\n        \"label\": \"Email Campaign\",\n        \"name\": \"Email Campaign\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"description\": \"Send mass SMS to your contacts\",\n        \"label\": \"SMS Center\",\n        \"name\": \"SMS Center\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"description\": \"Logs for maintaining sms delivery status\",\n        \"label\": \"SMS Log\",\n        \"name\": \"SMS Log\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"description\": \"Setup SMS gateway settings\",\n        \"label\": \"SMS Settings\",\n        \"name\": \"SMS Settings\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"Email Group\",\n        \"name\": \"Email Group\",\n        \"type\": \"doctype\"\n    }\n]"
+   "label": "Maintenance",
+   "links": "[\n    {\n        \"description\": \"Plan for maintenance visits.\",\n        \"label\": \"Maintenance Schedule\",\n        \"name\": \"Maintenance Schedule\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n    },\n    {\n        \"description\": \"Visit report for maintenance call.\",\n        \"label\": \"Maintenance Visit\",\n        \"name\": \"Maintenance Visit\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"description\": \"Warranty Claim against Serial No.\",\n        \"label\": \"Warranty Claim\",\n        \"name\": \"Warranty Claim\",\n        \"type\": \"doctype\"\n    }\n]"
   },
   {
    "hidden": 0,
-   "label": "Maintenance",
-   "links": "[\n    {\n        \"description\": \"Plan for maintenance visits.\",\n        \"label\": \"Maintenance Schedule\",\n        \"name\": \"Maintenance Schedule\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n    },\n    {\n        \"description\": \"Visit report for maintenance call.\",\n        \"label\": \"Maintenance Visit\",\n        \"name\": \"Maintenance Visit\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"description\": \"Warranty Claim against Serial No.\",\n        \"label\": \"Warranty Claim\",\n        \"name\": \"Warranty Claim\",\n        \"type\": \"doctype\"\n    }\n]"
+   "label": "Campaign",
+   "links": "[\n    {\n        \"description\": \"Sales campaigns.\",\n        \"label\": \"Campaign\",\n        \"name\": \"Campaign\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"description\": \"Sends Mails to lead or contact based on a Campaign schedule\",\n        \"label\": \"Email Campaign\",\n        \"name\": \"Email Campaign\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"description\": \"Create and Schedule social media posts\",\n        \"label\": \"Social Media Post\",\n        \"name\": \"Social Media Post\",\n        \"type\": \"doctype\"\n    }\n]"
+  },
+  {
+   "hidden": 0,
+   "label": "Settings",
+   "links": "[\n    {\n        \"description\": \"Manage Customer Group Tree.\",\n        \"icon\": \"fa fa-sitemap\",\n        \"label\": \"Customer Group\",\n        \"link\": \"Tree/Customer Group\",\n        \"name\": \"Customer Group\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n    },\n    {\n        \"description\": \"Manage Territory Tree.\",\n        \"icon\": \"fa fa-sitemap\",\n        \"label\": \"Territory\",\n        \"link\": \"Tree/Territory\",\n        \"name\": \"Territory\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n    },\n    {\n        \"description\": \"Manage Sales Person Tree.\",\n        \"icon\": \"fa fa-sitemap\",\n        \"label\": \"Sales Person\",\n        \"link\": \"Tree/Sales Person\",\n        \"name\": \"Sales Person\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n    },\n    {\n        \"description\": \"Send mass SMS to your contacts\",\n        \"label\": \"SMS Center\",\n        \"name\": \"SMS Center\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"description\": \"Logs for maintaining sms delivery status\",\n        \"label\": \"SMS Log\",\n        \"name\": \"SMS Log\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"description\": \"Setup SMS gateway settings\",\n        \"label\": \"SMS Settings\",\n        \"name\": \"SMS Settings\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"Email Group\",\n        \"name\": \"Email Group\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"Twitter Settings\",\n        \"name\": \"Twitter Settings\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"LinkedIn Settings\",\n        \"name\": \"LinkedIn Settings\",\n        \"type\": \"doctype\"\n    }\n]"
   }
  ],
  "category": "Modules",
@@ -33,7 +38,7 @@
  "idx": 0,
  "is_standard": 1,
  "label": "CRM",
- "modified": "2020-04-01 11:28:51.219999",
+ "modified": "2020-04-27 22:32:26.682911",
  "modified_by": "Administrator",
  "module": "CRM",
  "name": "CRM",
@@ -42,7 +47,7 @@
  "pin_to_top": 0,
  "shortcuts": [
   {
-   "format": "Open",
+   "format": "{} Open",
    "label": "Lead",
    "link_to": "Lead",
    "stats_filter": "{\"status\":\"Open\"}",
diff --git a/erpnext/crm/doctype/email_campaign/email_campaign.py b/erpnext/crm/doctype/email_campaign/email_campaign.py
index 00a4bd1..8f60ecf 100644
--- a/erpnext/crm/doctype/email_campaign/email_campaign.py
+++ b/erpnext/crm/doctype/email_campaign/email_campaign.py
@@ -27,7 +27,7 @@
 		for entry in campaign.get("campaign_schedules"):
 			send_after_days.append(entry.send_after_days)
 		try:
-			end_date = add_days(getdate(self.start_date), max(send_after_days))
+			self.end_date = add_days(getdate(self.start_date), max(send_after_days))
 		except ValueError:
 			frappe.throw(_("Please set up the Campaign Schedule in the Campaign {0}").format(self.campaign_name))
 
diff --git a/erpnext/accounts/doctype/account_subtype/__init__.py b/erpnext/crm/doctype/linkedin_settings/__init__.py
similarity index 100%
copy from erpnext/accounts/doctype/account_subtype/__init__.py
copy to erpnext/crm/doctype/linkedin_settings/__init__.py
diff --git a/erpnext/crm/doctype/linkedin_settings/linkedin_settings.js b/erpnext/crm/doctype/linkedin_settings/linkedin_settings.js
new file mode 100644
index 0000000..50b98e9
--- /dev/null
+++ b/erpnext/crm/doctype/linkedin_settings/linkedin_settings.js
@@ -0,0 +1,71 @@
+// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+frappe.ui.form.on('LinkedIn Settings', {
+	onload: function(frm){
+		if (frm.doc.session_status == 'Expired' && frm.doc.consumer_key && frm.doc.consumer_secret){
+			frappe.confirm(
+				__('Session not valid, Do you want to login?'),
+				function(){
+					frm.trigger("login");
+				},
+				function(){
+					window.close();
+				}
+			);
+		}
+	},
+	refresh: function(frm){
+		if (frm.doc.session_status=="Expired"){
+			let msg = __("Session Not Active. Save doc to login.");
+			frm.dashboard.set_headline_alert(
+				`<div class="row">
+					<div class="col-xs-12">
+						<span class="indicator whitespace-nowrap red"><span class="hidden-xs">${msg}</span></span>
+					</div>
+				</div>`
+			);
+		}
+
+		if (frm.doc.session_status=="Active"){
+			let d = new Date(frm.doc.modified);
+			d.setDate(d.getDate()+60);
+			let dn = new Date();
+			let days = d.getTime() - dn.getTime();
+			days = Math.floor(days/(1000 * 3600 * 24));
+			let msg,color;
+
+			if (days>0){
+				msg = __("Your Session will be expire in ") + days + __(" days.");
+				color = "green";
+			}
+			else {
+				msg = __("Session is expired. Save doc to login.");
+				color = "red";
+			}
+
+			frm.dashboard.set_headline_alert(
+				`<div class="row">
+					<div class="col-xs-12">
+						<span class="indicator whitespace-nowrap ${color}"><span class="hidden-xs">${msg}</span></span>
+					</div>
+				</div>`
+			);
+		}
+	},
+	login: function(frm){
+		if (frm.doc.consumer_key && frm.doc.consumer_secret){
+			frappe.dom.freeze();
+			frappe.call({
+				doc: frm.doc,
+				method: "get_authorization_url",
+				callback : function(r) {
+					window.location.href = r.message;
+				}
+			});
+		}
+	},
+	after_save: function(frm){
+		frm.trigger("login");
+	}
+});
diff --git a/erpnext/crm/doctype/linkedin_settings/linkedin_settings.json b/erpnext/crm/doctype/linkedin_settings/linkedin_settings.json
new file mode 100644
index 0000000..9eacb00
--- /dev/null
+++ b/erpnext/crm/doctype/linkedin_settings/linkedin_settings.json
@@ -0,0 +1,111 @@
+{
+ "actions": [],
+ "creation": "2020-01-30 13:36:39.492931",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "account_name",
+  "column_break_2",
+  "company_id",
+  "oauth_details",
+  "consumer_key",
+  "column_break_5",
+  "consumer_secret",
+  "user_details_section",
+  "access_token",
+  "person_urn",
+  "session_status"
+ ],
+ "fields": [
+  {
+   "fieldname": "account_name",
+   "fieldtype": "Data",
+   "label": "Account Name",
+   "read_only": 1
+  },
+  {
+   "fieldname": "oauth_details",
+   "fieldtype": "Section Break",
+   "label": "OAuth Credentials"
+  },
+  {
+   "fieldname": "consumer_key",
+   "fieldtype": "Data",
+   "in_list_view": 1,
+   "label": "Consumer Key",
+   "reqd": 1
+  },
+  {
+   "fieldname": "consumer_secret",
+   "fieldtype": "Password",
+   "in_list_view": 1,
+   "label": "Consumer Secret",
+   "reqd": 1
+  },
+  {
+   "fieldname": "access_token",
+   "fieldtype": "Data",
+   "hidden": 1,
+   "label": "Access Token",
+   "read_only": 1
+  },
+  {
+   "fieldname": "person_urn",
+   "fieldtype": "Data",
+   "hidden": 1,
+   "label": "Person URN",
+   "read_only": 1
+  },
+  {
+   "fieldname": "column_break_5",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "user_details_section",
+   "fieldtype": "Section Break",
+   "label": "User Details"
+  },
+  {
+   "fieldname": "session_status",
+   "fieldtype": "Select",
+   "hidden": 1,
+   "label": "Session Status",
+   "options": "Expired\nActive",
+   "read_only": 1
+  },
+  {
+   "fieldname": "column_break_2",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "company_id",
+   "fieldtype": "Data",
+   "label": "Company ID",
+   "reqd": 1
+  }
+ ],
+ "issingle": 1,
+ "links": [],
+ "modified": "2020-04-16 23:22:51.966397",
+ "modified_by": "Administrator",
+ "module": "CRM",
+ "name": "LinkedIn Settings",
+ "owner": "Administrator",
+ "permissions": [
+  {
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "print": 1,
+   "read": 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/crm/doctype/linkedin_settings/linkedin_settings.py b/erpnext/crm/doctype/linkedin_settings/linkedin_settings.py
new file mode 100644
index 0000000..5df35df
--- /dev/null
+++ b/erpnext/crm/doctype/linkedin_settings/linkedin_settings.py
@@ -0,0 +1,166 @@
+# -*- 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, requests, json
+from frappe import _
+from frappe.utils import get_site_url, get_url_to_form, get_link_to_form
+from frappe.model.document import Document
+from frappe.utils.file_manager import get_file, get_file_path
+from six.moves.urllib.parse import urlencode
+
+class LinkedInSettings(Document):
+	def get_authorization_url(self):	
+		params = urlencode({
+			"response_type":"code",
+			"client_id": self.consumer_key,
+			"redirect_uri": get_site_url(frappe.local.site) + "/?cmd=erpnext.crm.doctype.linkedin_settings.linkedin_settings.callback",
+			"scope": "r_emailaddress w_organization_social r_basicprofile r_liteprofile r_organization_social rw_organization_admin w_member_social"
+		})
+
+		url = "https://www.linkedin.com/oauth/v2/authorization?{}".format(params)
+
+		return url
+
+	def get_access_token(self, code):
+		url = "https://www.linkedin.com/oauth/v2/accessToken"
+		body = {
+			"grant_type": "authorization_code",
+			"code": code,
+			"client_id": self.consumer_key,
+			"client_secret": self.get_password(fieldname="consumer_secret"),
+			"redirect_uri": get_site_url(frappe.local.site) + "/?cmd=erpnext.crm.doctype.linkedin_settings.linkedin_settings.callback",
+		}
+		headers = {
+			"Content-Type": "application/x-www-form-urlencoded"
+		}
+		
+		response = self.http_post(url=url, data=body, headers=headers)
+		response = frappe.parse_json(response.content.decode())
+		self.db_set("access_token", response["access_token"])
+
+	def get_member_profile(self):
+		headers = {
+			"Authorization": "Bearer {}".format(self.access_token)
+		}
+		url = "https://api.linkedin.com/v2/me"
+		response = requests.get(url=url, headers=headers)
+		response = frappe.parse_json(response.content.decode())
+
+		frappe.db.set_value(self.doctype, self.name, {
+			"person_urn": response["id"],
+			"account_name": response["vanityName"],
+			"session_status": "Active"
+		})
+		frappe.local.response["type"] = "redirect"
+		frappe.local.response["location"] = get_url_to_form("LinkedIn Settings","LinkedIn Settings")
+
+	def post(self, text, media=None):
+		if not media:
+			return self.post_text(text)
+		else:
+			media_id = self.upload_image(media)
+
+			if media_id:
+				return self.post_text(text, media_id=media_id)
+			else:
+				frappe.log_error("Failed to upload media.","LinkedIn Upload Error")
+
+
+	def upload_image(self, media):
+		media = get_file_path(media)
+		register_url = "https://api.linkedin.com/v2/assets?action=registerUpload"
+		body = {
+			"registerUploadRequest": {
+				"recipes": ["urn:li:digitalmediaRecipe:feedshare-image"],
+				"owner": "urn:li:organization:{0}".format(self.company_id),
+				"serviceRelationships": [{
+					"relationshipType": "OWNER",
+					"identifier": "urn:li:userGeneratedContent"
+				}]
+			}
+		}
+		headers = {
+			"Authorization": "Bearer {}".format(self.access_token)
+		}
+		response = self.http_post(url=register_url, body=body, headers=headers)
+
+		if response.status_code == 200:
+			response = response.json()
+			asset = response["value"]["asset"]
+			upload_url = response["value"]["uploadMechanism"]["com.linkedin.digitalmedia.uploading.MediaUploadHttpRequest"]["uploadUrl"]
+			headers['Content-Type']='image/jpeg'
+			response = self.http_post(upload_url, headers=headers, data=open(media,"rb"))
+			if response.status_code < 200 and response.status_code > 299:
+				frappe.throw(_("Error While Uploading Image"), title="{0} {1}".format(response.status_code, response.reason))
+				return None
+			return asset
+
+		return None
+
+	def post_text(self, text, media_id=None):
+		url = "https://api.linkedin.com/v2/shares"
+		headers = {
+			"X-Restli-Protocol-Version": "2.0.0",
+			"Authorization": "Bearer {}".format(self.access_token),
+			"Content-Type": "application/json; charset=UTF-8"
+		}
+		body = {
+			"distribution": {
+				"linkedInDistributionTarget": {}
+			},
+			"owner":"urn:li:organization:{0}".format(self.company_id),
+			"subject": "Test Share Subject",
+			"text": {
+				"text": text
+			}
+		}
+
+		if media_id:
+			body["content"]= {
+				"contentEntities": [{
+					"entity": media_id
+				}],
+				"shareMediaCategory": "IMAGE"
+			}
+
+		response = self.http_post(url=url, headers=headers, body=body)
+		return response
+
+	def http_post(self, url, headers=None, body=None, data=None):
+		try:
+			response = requests.post(
+				url = url,
+				json = body,
+				data = data,
+				headers = headers
+			)
+			if response.status_code not in [201,200]:
+				raise
+
+		except Exception as e:
+			content = json.loads(response.content)
+
+			if response.status_code == 401:
+				self.db_set("session_status", "Expired")
+				frappe.db.commit()
+				frappe.throw(content["message"], title="LinkedIn Error - Unauthorized")
+			elif response.status_code == 403:
+				frappe.msgprint(_("You Didn't have permission to access this API"))
+				frappe.throw(content["message"], title="LinkedIn Error - Access Denied")
+			else:
+				frappe.throw(response.reason, title=response.status_code)
+
+		return response
+
+@frappe.whitelist()
+def callback(code=None, error=None, error_description=None):
+	if not error:
+		linkedin_settings = frappe.get_doc("LinkedIn Settings")
+		linkedin_settings.get_access_token(code)
+		linkedin_settings.get_member_profile()
+		frappe.db.commit()
+	else:
+		frappe.local.response["type"] = "redirect"
+		frappe.local.response["location"] = get_url_to_form("LinkedIn Settings","LinkedIn Settings")
diff --git a/erpnext/crm/doctype/linkedin_settings/test_linkedin_settings.py b/erpnext/crm/doctype/linkedin_settings/test_linkedin_settings.py
new file mode 100644
index 0000000..9c3ef3f
--- /dev/null
+++ b/erpnext/crm/doctype/linkedin_settings/test_linkedin_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 TestLinkedInSettings(unittest.TestCase):
+	pass
diff --git a/erpnext/accounts/doctype/account_subtype/__init__.py b/erpnext/crm/doctype/social_media_post/__init__.py
similarity index 100%
copy from erpnext/accounts/doctype/account_subtype/__init__.py
copy to erpnext/crm/doctype/social_media_post/__init__.py
diff --git a/erpnext/crm/doctype/social_media_post/social_media_post.js b/erpnext/crm/doctype/social_media_post/social_media_post.js
new file mode 100644
index 0000000..3a14f2d
--- /dev/null
+++ b/erpnext/crm/doctype/social_media_post/social_media_post.js
@@ -0,0 +1,67 @@
+// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+frappe.ui.form.on('Social Media Post', {
+    validate: function(frm){
+        if (frm.doc.twitter === 0 && frm.doc.linkedin === 0){
+            frappe.throw(__("Select atleast one Social Media from Share on."))
+        }
+        if (frm.doc.scheduled_time) {
+            let scheduled_time = new Date(frm.doc.scheduled_time);
+            let date_time = new Date();
+            if (scheduled_time.getTime() < date_time.getTime()){
+                frappe.throw(__("Invalid Scheduled Time"));
+            }
+        }
+        if (frm.doc.text?.length > 280){
+            frappe.throw(__("Length Must be less than 280."))
+        }
+    },
+	refresh: function(frm){
+        if (frm.doc.docstatus === 1){
+            if (frm.doc.post_status != "Posted"){
+                add_post_btn(frm); 
+            }
+            else if (frm.doc.post_status == "Posted"){
+                frm.set_df_property('sheduled_time', 'read_only', 1);
+            }
+
+            let html='';
+            if (frm.doc.twitter){
+                let color = frm.doc.twitter_post_id ? "green" : "red";
+                let status = frm.doc.twitter_post_id ? "Posted" : "Not Posted";
+                html += `<div class="col-xs-6">
+                            <span class="indicator whitespace-nowrap ${color}"><span class="hidden-xs">Twitter : ${status} </span></span>
+                        </div>` ;
+            }
+            if (frm.doc.linkedin){
+                let color = frm.doc.linkedin_post_id ? "green" : "red";
+                let status = frm.doc.linkedin_post_id ? "Posted" : "Not Posted";
+                html += `<div class="col-xs-6">
+                            <span class="indicator whitespace-nowrap ${color}"><span class="hidden-xs">LinkedIn : ${status} </span></span>
+                        </div>` ;
+            }
+            html = `<div class="row">${html}</div>`;
+            frm.dashboard.set_headline_alert(html);
+        }
+    }
+});
+var add_post_btn = function(frm){
+    frm.add_custom_button(('Post Now'), function(){
+        post(frm);
+    });
+}
+var post = function(frm){
+    frappe.dom.freeze();
+    frappe.call({
+        method: "erpnext.crm.doctype.social_media_post.social_media_post.publish",
+        args: {
+            doctype: frm.doc.doctype,
+            name: frm.doc.name
+        },
+        callback: function(r) {
+            frm.reload_doc();
+            frappe.dom.unfreeze();
+        }
+    })
+    
+}
\ No newline at end of file
diff --git a/erpnext/crm/doctype/social_media_post/social_media_post.json b/erpnext/crm/doctype/social_media_post/social_media_post.json
new file mode 100644
index 0000000..2601c14
--- /dev/null
+++ b/erpnext/crm/doctype/social_media_post/social_media_post.json
@@ -0,0 +1,166 @@
+{
+ "actions": [],
+ "autoname": "format: CRM-SMP-{YYYY}-{MM}-{DD}-{###}",
+ "creation": "2020-01-30 11:53:13.872864",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "campaign_name",
+  "scheduled_time",
+  "post_status",
+  "column_break_6",
+  "twitter",
+  "linkedin",
+  "twitter_post_id",
+  "linkedin_post_id",
+  "content",
+  "text",
+  "column_break_14",
+  "tweet_preview",
+  "linkedin_section",
+  "linkedin_post",
+  "column_break_15",
+  "attachments_section",
+  "image",
+  "amended_from"
+ ],
+ "fields": [
+  {
+   "fieldname": "text",
+   "fieldtype": "Small Text",
+   "label": "Tweet",
+   "mandatory_depends_on": "eval:doc.twitter ==1"
+  },
+  {
+   "fieldname": "image",
+   "fieldtype": "Attach Image",
+   "label": "Image"
+  },
+  {
+   "default": "0",
+   "fieldname": "twitter",
+   "fieldtype": "Check",
+   "label": "Twitter"
+  },
+  {
+   "default": "0",
+   "fieldname": "linkedin",
+   "fieldtype": "Check",
+   "label": "LinkedIn"
+  },
+  {
+   "fieldname": "amended_from",
+   "fieldtype": "Link",
+   "label": "Amended From",
+   "no_copy": 1,
+   "options": "Social Media Post",
+   "print_hide": 1,
+   "read_only": 1
+  },
+  {
+   "depends_on": "eval:doc.twitter ==1",
+   "fieldname": "content",
+   "fieldtype": "Section Break",
+   "label": "Twitter"
+  },
+  {
+   "allow_on_submit": 1,
+   "fieldname": "post_status",
+   "fieldtype": "Select",
+   "label": "Post Status",
+   "options": "\nScheduled\nPosted\nError",
+   "read_only": 1
+  },
+  {
+   "allow_on_submit": 1,
+   "fieldname": "twitter_post_id",
+   "fieldtype": "Data",
+   "hidden": 1,
+   "label": "Twitter Post Id",
+   "read_only": 1
+  },
+  {
+   "allow_on_submit": 1,
+   "fieldname": "linkedin_post_id",
+   "fieldtype": "Data",
+   "hidden": 1,
+   "label": "LinkedIn Post Id",
+   "read_only": 1
+  },
+  {
+   "fieldname": "campaign_name",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "label": "Campaign",
+   "options": "Campaign"
+  },
+  {
+   "fieldname": "column_break_6",
+   "fieldtype": "Column Break",
+   "label": "Share On"
+  },
+  {
+   "fieldname": "column_break_14",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "tweet_preview",
+   "fieldtype": "HTML"
+  },
+  {
+   "collapsible": 1,
+   "depends_on": "eval:doc.linkedin==1",
+   "fieldname": "linkedin_section",
+   "fieldtype": "Section Break",
+   "label": "LinkedIn"
+  },
+  {
+   "collapsible": 1,
+   "fieldname": "attachments_section",
+   "fieldtype": "Section Break",
+   "label": "Attachments"
+  },
+  {
+   "fieldname": "linkedin_post",
+   "fieldtype": "Text",
+   "label": "Post",
+   "mandatory_depends_on": "eval:doc.linkedin ==1"
+  },
+  {
+   "fieldname": "column_break_15",
+   "fieldtype": "Column Break"
+  },
+  {
+   "allow_on_submit": 1,
+   "fieldname": "scheduled_time",
+   "fieldtype": "Datetime",
+   "label": "Scheduled Time",
+   "read_only_depends_on": "eval:doc.post_status == \"Posted\""
+  }
+ ],
+ "is_submittable": 1,
+ "links": [],
+ "modified": "2020-04-21 15:10:04.953713",
+ "modified_by": "Administrator",
+ "module": "CRM",
+ "name": "Social Media Post",
+ "owner": "Administrator",
+ "permissions": [
+  {
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "export": 1,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "System Manager",
+   "share": 1,
+   "write": 1
+  }
+ ],
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/crm/doctype/social_media_post/social_media_post.py b/erpnext/crm/doctype/social_media_post/social_media_post.py
new file mode 100644
index 0000000..ed1b583
--- /dev/null
+++ b/erpnext/crm/doctype/social_media_post/social_media_post.py
@@ -0,0 +1,56 @@
+# -*- 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 frappe import _
+import datetime
+
+class SocialMediaPost(Document):
+	def validate(self):
+		if self.scheduled_time:
+			current_time = frappe.utils.now_datetime()
+			scheduled_time = frappe.utils.get_datetime(self.scheduled_time)
+			if scheduled_time < current_time:
+				frappe.throw(_("Invalid Scheduled Time"))
+
+	def submit(self):
+		if self.scheduled_time:
+			self.post_status = "Scheduled"
+		super(SocialMediaPost, self).submit()
+
+	def post(self):
+		try:
+			if self.twitter and not self.twitter_post_id:
+				twitter = frappe.get_doc("Twitter Settings")
+				twitter_post = twitter.post(self.text, self.image)
+				self.db_set("twitter_post_id", twitter_post.id)
+			if self.linkedin and not self.linkedin_post_id:
+				linkedin = frappe.get_doc("LinkedIn Settings")
+				linkedin_post = linkedin.post(self.linkedin_post, self.image)
+				self.db_set("linkedin_post_id", linkedin_post.headers['X-RestLi-Id'].split(":")[-1])
+			self.db_set("post_status", "Posted")
+
+		except:
+			self.db_set("post_status", "Error")
+			title = _("Error while POSTING {0}").format(self.name)
+			traceback = frappe.get_traceback()
+			frappe.log_error(message=traceback , title=title)
+
+def process_scheduled_social_media_posts():
+	posts = frappe.get_list("Social Media Post", filters={"post_status": "Scheduled", "docstatus":1}, fields= ["name", "scheduled_time","post_status"])
+	start = frappe.utils.now_datetime()
+	end = start + datetime.timedelta(minutes=10)
+	for post in posts:
+		if post.scheduled_time:
+			post_time = frappe.utils.get_datetime(post.scheduled_time)
+			if post_time > start and post_time <= end:
+				publish('Social Media Post', post.name)
+
+@frappe.whitelist()
+def publish(doctype, name):
+	sm_post = frappe.get_doc(doctype, name)
+	sm_post.post()
+	frappe.db.commit()
diff --git a/erpnext/crm/doctype/social_media_post/social_media_post_list.js b/erpnext/crm/doctype/social_media_post/social_media_post_list.js
new file mode 100644
index 0000000..c60b91a
--- /dev/null
+++ b/erpnext/crm/doctype/social_media_post/social_media_post_list.js
@@ -0,0 +1,10 @@
+frappe.listview_settings['Social Media Post'] = {
+    add_fields: ["status","post_status"],
+    get_indicator: function(doc) {
+        return [__(doc.post_status), {
+            "Scheduled": "orange",
+            "Posted": "green",
+            "Error": "red"
+            }[doc.post_status]];
+        }
+}
diff --git a/erpnext/crm/doctype/social_media_post/test_social_media_post.py b/erpnext/crm/doctype/social_media_post/test_social_media_post.py
new file mode 100644
index 0000000..ec81ee5
--- /dev/null
+++ b/erpnext/crm/doctype/social_media_post/test_social_media_post.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 TestSocialMediaPost(unittest.TestCase):
+	pass
diff --git a/erpnext/accounts/doctype/account_subtype/__init__.py b/erpnext/crm/doctype/twitter_settings/__init__.py
similarity index 100%
copy from erpnext/accounts/doctype/account_subtype/__init__.py
copy to erpnext/crm/doctype/twitter_settings/__init__.py
diff --git a/erpnext/crm/doctype/twitter_settings/test_twitter_settings.py b/erpnext/crm/doctype/twitter_settings/test_twitter_settings.py
new file mode 100644
index 0000000..3f999c1
--- /dev/null
+++ b/erpnext/crm/doctype/twitter_settings/test_twitter_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 TestTwitterSettings(unittest.TestCase):
+	pass
diff --git a/erpnext/crm/doctype/twitter_settings/twitter_settings.js b/erpnext/crm/doctype/twitter_settings/twitter_settings.js
new file mode 100644
index 0000000..b55946a
--- /dev/null
+++ b/erpnext/crm/doctype/twitter_settings/twitter_settings.js
@@ -0,0 +1,56 @@
+// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+frappe.ui.form.on('Twitter Settings', {
+	onload: function(frm){
+		if (frm.doc.session_status == 'Expired' && frm.doc.consumer_key && frm.doc.consumer_secret){
+			frappe.confirm(
+				__('Session not valid, Do you want to login?'),
+				function(){
+					frm.trigger("login");
+				},
+				function(){
+					window.close();
+				}
+			);
+		}
+	},
+	refresh: function(frm){
+		let msg, color, flag=false;
+		if (frm.doc.session_status == "Active"){
+			msg = __("Session Active");
+			color = 'green';
+			flag = true;
+		}
+		else if(frm.doc.consumer_key && frm.doc.consumer_secret) {
+			msg = __("Session Not Active. Save doc to login.");
+			color = 'red';
+			flag = true;
+		}
+
+		if (flag){
+			frm.dashboard.set_headline_alert(
+				`<div class="row">
+					<div class="col-xs-12">
+						<span class="indicator whitespace-nowrap ${color}"><span class="hidden-xs">${msg}</span></span>
+					</div>
+				</div>`
+			);
+		}
+	},
+	login: function(frm){
+		if (frm.doc.consumer_key && frm.doc.consumer_secret){
+			frappe.dom.freeze();
+			frappe.call({
+				doc: frm.doc,
+				method: "get_authorize_url",
+				callback : function(r) {
+					window.location.href = r.message;
+				}
+			});
+		}
+	},
+	after_save: function(frm){
+		frm.trigger("login");
+	}
+});
diff --git a/erpnext/crm/doctype/twitter_settings/twitter_settings.json b/erpnext/crm/doctype/twitter_settings/twitter_settings.json
new file mode 100644
index 0000000..f92e7f0
--- /dev/null
+++ b/erpnext/crm/doctype/twitter_settings/twitter_settings.json
@@ -0,0 +1,101 @@
+{
+ "actions": [],
+ "creation": "2020-01-30 10:29:08.562108",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "account_name",
+  "profile_pic",
+  "oauth_details",
+  "consumer_key",
+  "column_break_5",
+  "consumer_secret",
+  "oauth_token",
+  "oauth_secret",
+  "session_status"
+ ],
+ "fields": [
+  {
+   "fieldname": "account_name",
+   "fieldtype": "Data",
+   "label": "Account Name",
+   "read_only": 1
+  },
+  {
+   "fieldname": "oauth_details",
+   "fieldtype": "Section Break",
+   "label": "OAuth Credentials"
+  },
+  {
+   "fieldname": "consumer_key",
+   "fieldtype": "Data",
+   "in_list_view": 1,
+   "label": "API Key",
+   "reqd": 1
+  },
+  {
+   "fieldname": "consumer_secret",
+   "fieldtype": "Password",
+   "in_list_view": 1,
+   "label": "API Secret Key",
+   "reqd": 1
+  },
+  {
+   "fieldname": "oauth_token",
+   "fieldtype": "Data",
+   "hidden": 1,
+   "label": "OAuth Token",
+   "read_only": 1
+  },
+  {
+   "fieldname": "oauth_secret",
+   "fieldtype": "Password",
+   "hidden": 1,
+   "label": "OAuth Token Secret",
+   "read_only": 1
+  },
+  {
+   "fieldname": "column_break_5",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "profile_pic",
+   "fieldtype": "Attach Image",
+   "hidden": 1,
+   "read_only": 1
+  },
+  {
+   "fieldname": "session_status",
+   "fieldtype": "Select",
+   "hidden": 1,
+   "label": "Session Status",
+   "options": "Expired\nActive",
+   "read_only": 1
+  }
+ ],
+ "image_field": "profile_pic",
+ "issingle": 1,
+ "links": [],
+ "modified": "2020-04-21 22:06:43.726798",
+ "modified_by": "Administrator",
+ "module": "CRM",
+ "name": "Twitter Settings",
+ "owner": "Administrator",
+ "permissions": [
+  {
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "print": 1,
+   "read": 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/crm/doctype/twitter_settings/twitter_settings.py b/erpnext/crm/doctype/twitter_settings/twitter_settings.py
new file mode 100644
index 0000000..64f53b5
--- /dev/null
+++ b/erpnext/crm/doctype/twitter_settings/twitter_settings.py
@@ -0,0 +1,98 @@
+# -*- 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, os, tweepy, json
+from frappe import _
+from frappe.model.document import Document
+from frappe.utils.file_manager import get_file_path
+from frappe.utils import get_url_to_form, get_link_to_form
+from tweepy.error import TweepError
+
+class TwitterSettings(Document):
+	def get_authorize_url(self):
+		callback_url = "{0}/?cmd=erpnext.crm.doctype.twitter_settings.twitter_settings.callback".format(frappe.utils.get_url())
+		auth = tweepy.OAuthHandler(self.consumer_key, self.get_password(fieldname="consumer_secret"), callback_url)
+
+		try:
+			redirect_url = auth.get_authorization_url()
+			return redirect_url
+		except:
+			frappe.msgprint(_("Error! Failed to get request token."))
+			frappe.throw(_('Invalid {0} or {1}').format(frappe.bold("Consumer Key"), frappe.bold("Consumer Secret Key")))
+
+	
+	def get_access_token(self, oauth_token, oauth_verifier):
+		auth = tweepy.OAuthHandler(self.consumer_key, self.get_password(fieldname="consumer_secret"))
+		auth.request_token = { 
+			'oauth_token' : oauth_token,
+			'oauth_token_secret' : oauth_verifier 
+		}
+
+		try:
+			auth.get_access_token(oauth_verifier)
+			api = self.get_api()
+			user = api.me()
+			profile_pic = (user._json["profile_image_url"]).replace("_normal","")
+
+			frappe.db.set_value(self.doctype, self.name, {
+				"oauth_token" : auth.access_token,
+				"oauth_secret" : auth.access_token_secret,
+				"account_name" : user._json["screen_name"],
+				"profile_pic" : profile_pic,
+				"session_status" : "Active"
+			})
+
+			frappe.local.response["type"] = "redirect"
+			frappe.local.response["location"] = get_url_to_form("Twitter Settings","Twitter Settings")
+		except TweepError as e:
+			frappe.msgprint(_("Error! Failed to get access token."))
+			frappe.throw(_('Invalid Consumer Key or Consumer Secret Key'))
+
+	def get_api(self):
+		# authentication of consumer key and secret 
+		auth = tweepy.OAuthHandler(self.consumer_key, self.get_password(fieldname="consumer_secret")) 
+		# authentication of access token and secret 
+		auth.set_access_token(self.oauth_token, self.get_password(fieldname="oauth_secret")) 
+
+		return tweepy.API(auth)
+
+	def post(self, text, media=None):
+		if not media:
+			return self.send_tweet(text)
+
+		if media:
+			media_id = self.upload_image(media)
+			return self.send_tweet(text, media_id)
+	
+	def upload_image(self, media):
+		media = get_file_path(media)
+		api = self.get_api()
+		media = api.media_upload(media)
+
+		return media.media_id
+
+	def send_tweet(self, text, media_id=None):
+		api = self.get_api()
+		try:
+			if media_id:
+				response = api.update_status(status = text, media_ids = [media_id])
+			else:
+				response = api.update_status(status = text)
+
+			return response
+
+		except TweepError as e:
+			content = json.loads(e.response.content)
+			content = content["errors"][0]
+			if e.response.status_code == 401:
+				self.db_set("session_status", "Expired")
+				frappe.db.commit()
+			frappe.throw(content["message"],title="Twitter Error {0} {1}".format(e.response.status_code, e.response.reason))
+
+@frappe.whitelist()
+def callback(oauth_token, oauth_verifier):
+	twitter_settings = frappe.get_single("Twitter Settings")
+	twitter_settings.get_access_token(oauth_token,oauth_verifier)
+	frappe.db.commit()
diff --git a/erpnext/crm/utils.py b/erpnext/crm/utils.py
new file mode 100644
index 0000000..38bf79e
--- /dev/null
+++ b/erpnext/crm/utils.py
@@ -0,0 +1,24 @@
+import frappe
+
+
+def update_lead_phone_numbers(contact, method):
+	if contact.phone_nos:
+		contact_lead = contact.get_link_for("Lead")
+		if contact_lead:
+			phone = mobile_no = contact.phone_nos[0].phone
+
+			if len(contact.phone_nos) > 1:
+				# get the default phone number
+				primary_phones = [phone_doc.phone for phone_doc in contact.phone_nos if phone_doc.is_primary_phone]
+				if primary_phones:
+					phone = primary_phones[0]
+
+				# get the default mobile number
+				primary_mobile_nos = [phone_doc.phone for phone_doc in contact.phone_nos if phone_doc.is_primary_mobile_no]
+				if primary_mobile_nos:
+					mobile_no = primary_mobile_nos[0]
+
+			lead = frappe.get_doc("Lead", contact_lead)
+			lead.phone = phone
+			lead.mobile_no = mobile_no
+			lead.save()
diff --git a/erpnext/education/doctype/fees/fees.js b/erpnext/education/doctype/fees/fees.js
index e2c6f1d..17ef449 100644
--- a/erpnext/education/doctype/fees/fees.js
+++ b/erpnext/education/doctype/fees/fees.js
@@ -112,6 +112,8 @@
 				args: {
 					"dt": frm.doc.doctype,
 					"dn": frm.doc.name,
+					"party_type": "Student",
+					"party": frm.doc.student,
 					"recipient_id": frm.doc.student_email
 				},
 				callback: function(r) {
diff --git a/erpnext/education/doctype/fees/fees.py b/erpnext/education/doctype/fees/fees.py
index aa616e6..f0d60fa 100644
--- a/erpnext/education/doctype/fees/fees.py
+++ b/erpnext/education/doctype/fees/fees.py
@@ -10,7 +10,7 @@
 from erpnext.accounts.doctype.payment_request.payment_request import make_payment_request
 from frappe.utils.csvutils import getlink
 from erpnext.controllers.accounts_controller import AccountsController
-from erpnext.accounts.general_ledger import delete_gl_entries
+from erpnext.accounts.general_ledger import make_reverse_gl_entries
 
 
 class Fees(AccountsController):
@@ -75,12 +75,14 @@
 		self.make_gl_entries()
 
 		if self.send_payment_request and self.student_email:
-			pr = make_payment_request(dt="Fees", dn=self.name, recipient_id=self.student_email,
+			pr = make_payment_request(party_type="Student", party=self.student, dt="Fees",
+					dn=self.name, recipient_id=self.student_email,
 					submit_doc=True, use_dummy_message=True)
 			frappe.msgprint(_("Payment request {0} created").format(getlink("Payment Request", pr.name)))
 
 	def on_cancel(self):
-		delete_gl_entries(voucher_type=self.doctype, voucher_no=self.name)
+		self.ignore_linked_doctypes = ('GL Entry', 'Stock Ledger Entry')
+		make_reverse_gl_entries(voucher_type=self.doctype, voucher_no=self.name)
 		# frappe.db.set(self, 'status', 'Cancelled')
 
 
diff --git a/erpnext/education/doctype/student/student_dashboard.py b/erpnext/education/doctype/student/student_dashboard.py
index 0cbd17b..d261462 100644
--- a/erpnext/education/doctype/student/student_dashboard.py
+++ b/erpnext/education/doctype/student/student_dashboard.py
@@ -6,6 +6,9 @@
 		'heatmap': True,
 		'heatmap_message': _('This is based on the attendance of this Student'),
 		'fieldname': 'student',
+		'non_standard_fieldnames': {
+			'Bank Account': 'party'
+		},
 		'transactions': [
 			{
 				'label': _('Admission'),
@@ -29,7 +32,7 @@
 			},
 			{
 				'label': _('Fee'),
-				'items': ['Fees']
+				'items': ['Fees', 'Bank Account']
 			}
 		]
-	}
\ No newline at end of file
+	}
diff --git a/erpnext/education/doctype/video/test_video.js b/erpnext/education/doctype/video/test_video.js
deleted file mode 100644
index a82a221..0000000
--- a/erpnext/education/doctype/video/test_video.js
+++ /dev/null
@@ -1,23 +0,0 @@
-/* eslint-disable */
-// rename this file from _test_[name] to test_[name] to activate
-// and remove above this line
-
-QUnit.test("test: Video", function (assert) {
-	let done = assert.async();
-
-	// number of asserts
-	assert.expect(1);
-
-	frappe.run_serially([
-		// insert a new Video
-		() => frappe.tests.make('Video', [
-			// values to be set
-			{key: 'value'}
-		]),
-		() => {
-			assert.equal(cur_frm.doc.key, 'value');
-		},
-		() => done()
-	]);
-
-});
diff --git a/erpnext/education/doctype/video/test_video.py b/erpnext/education/doctype/video/test_video.py
deleted file mode 100644
index ecb09a2..0000000
--- a/erpnext/education/doctype/video/test_video.py
+++ /dev/null
@@ -1,10 +0,0 @@
-# -*- coding: utf-8 -*-
-# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
-# See license.txt
-from __future__ import unicode_literals
-
-import frappe
-import unittest
-
-class TestVideo(unittest.TestCase):
-	pass
diff --git a/erpnext/education/doctype/video/video.js b/erpnext/education/doctype/video/video.js
deleted file mode 100644
index c35c19b..0000000
--- a/erpnext/education/doctype/video/video.js
+++ /dev/null
@@ -1,8 +0,0 @@
-// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
-// For license information, please see license.txt
-
-frappe.ui.form.on('Video', {
-	refresh: function(frm) {
-
-	}
-});
diff --git a/erpnext/education/doctype/video/video.json b/erpnext/education/doctype/video/video.json
deleted file mode 100644
index e912eb3..0000000
--- a/erpnext/education/doctype/video/video.json
+++ /dev/null
@@ -1,112 +0,0 @@
-{
- "allow_import": 1,
- "allow_rename": 1,
- "autoname": "field:title",
- "creation": "2018-10-17 05:47:13.087395",
- "doctype": "DocType",
- "editable_grid": 1,
- "engine": "InnoDB",
- "field_order": [
-  "title",
-  "provider",
-  "url",
-  "column_break_4",
-  "publish_date",
-  "duration",
-  "section_break_7",
-  "description"
- ],
- "fields": [
-  {
-   "fieldname": "title",
-   "fieldtype": "Data",
-   "in_list_view": 1,
-   "label": "Title",
-   "reqd": 1,
-   "unique": 1
-  },
-  {
-   "fieldname": "description",
-   "fieldtype": "Text Editor",
-   "in_list_view": 1,
-   "label": "Description",
-   "reqd": 1
-  },
-  {
-   "fieldname": "duration",
-   "fieldtype": "Data",
-   "label": "Duration"
-  },
-  {
-   "fieldname": "url",
-   "fieldtype": "Data",
-   "in_list_view": 1,
-   "label": "URL",
-   "reqd": 1
-  },
-  {
-   "fieldname": "publish_date",
-   "fieldtype": "Date",
-   "label": "Publish Date"
-  },
-  {
-   "fieldname": "provider",
-   "fieldtype": "Select",
-   "in_list_view": 1,
-   "label": "Provider",
-   "options": "YouTube\nVimeo",
-   "reqd": 1
-  },
-  {
-   "fieldname": "column_break_4",
-   "fieldtype": "Column Break"
-  },
-  {
-   "fieldname": "section_break_7",
-   "fieldtype": "Section Break"
-  }
- ],
- "modified": "2019-06-12 12:36:48.753092",
- "modified_by": "Administrator",
- "module": "Education",
- "name": "Video",
- "owner": "Administrator",
- "permissions": [
-  {
-   "create": 1,
-   "delete": 1,
-   "email": 1,
-   "export": 1,
-   "print": 1,
-   "read": 1,
-   "report": 1,
-   "role": "Academics User",
-   "share": 1,
-   "write": 1
-  },
-  {
-   "create": 1,
-   "delete": 1,
-   "email": 1,
-   "export": 1,
-   "print": 1,
-   "read": 1,
-   "report": 1,
-   "role": "Instructor",
-   "share": 1,
-   "write": 1
-  },
-  {
-   "email": 1,
-   "export": 1,
-   "print": 1,
-   "read": 1,
-   "report": 1,
-   "role": "LMS User",
-   "share": 1
-  }
- ],
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 1
-}
\ No newline at end of file
diff --git a/erpnext/education/doctype/video/video.py b/erpnext/education/doctype/video/video.py
deleted file mode 100644
index b19f812..0000000
--- a/erpnext/education/doctype/video/video.py
+++ /dev/null
@@ -1,13 +0,0 @@
-# -*- coding: utf-8 -*-
-# Copyright (c) 2018, 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 Video(Document):
-
-
-	def get_video(self):
-		pass
diff --git a/erpnext/erpnext_integrations/connectors/woocommerce_connection.py b/erpnext/erpnext_integrations/connectors/woocommerce_connection.py
index 4422d23..6188652 100644
--- a/erpnext/erpnext_integrations/connectors/woocommerce_connection.py
+++ b/erpnext/erpnext_integrations/connectors/woocommerce_connection.py
@@ -144,6 +144,10 @@
 def set_items_in_sales_order(new_sales_order, woocommerce_settings, order, sys_lang):
 	company_abbr = frappe.db.get_value('Company', woocommerce_settings.company, 'abbr')
 
+	default_warehouse = _("Stores - {0}", sys_lang).format(company_abbr)
+	if not frappe.db.exists("Warehouse", default_warehouse):
+		frappe.throw(_("Please set Warehouse in Woocommerce Settings"))
+
 	for item in order.get("line_items"):
 		woocomm_item_id = item.get("product_id")
 		found_item = frappe.get_doc("Item", {"woocommerce_id": woocomm_item_id})
@@ -158,7 +162,7 @@
 			"uom": woocommerce_settings.uom or _("Nos", sys_lang),
 			"qty": item.get("quantity"),
 			"rate": item.get("price"),
-			"warehouse": woocommerce_settings.warehouse or _("Stores - {0}", sys_lang).format(company_abbr)
+			"warehouse": woocommerce_settings.warehouse or default_warehouse
 			})
 
 		add_tax_details(new_sales_order, ordered_items_tax, "Ordered Item tax", woocommerce_settings.tax_account)
diff --git a/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_settings.py b/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_settings.py
index 7083950..b4a5bd1 100644
--- a/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_settings.py
+++ b/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_settings.py
@@ -67,11 +67,11 @@
 		frappe.throw(_("Please setup a default bank account for company {0}").format(company))
 
 	for account in response["accounts"]:
-		acc_type = frappe.db.get_value("Account Type", account["type"])
+		acc_type = frappe.db.get_value("Bank Account Type", account["type"])
 		if not acc_type:
 			add_account_type(account["type"])
 
-		acc_subtype = frappe.db.get_value("Account Subtype", account["subtype"])
+		acc_subtype = frappe.db.get_value("Bank Account Subtype", account["subtype"])
 		if not acc_subtype:
 			add_account_subtype(account["subtype"])
 
@@ -106,7 +106,7 @@
 def add_account_type(account_type):
 	try:
 		frappe.get_doc({
-			"doctype": "Account Type",
+			"doctype": "Bank Account Type",
 			"account_type": account_type
 		}).insert()
 	except Exception:
@@ -116,7 +116,7 @@
 def add_account_subtype(account_subtype):
 	try:
 		frappe.get_doc({
-			"doctype": "Account Subtype",
+			"doctype": "Bank Account Subtype",
 			"account_subtype": account_subtype
 		}).insert()
 	except Exception:
diff --git a/erpnext/erpnext_integrations/doctype/plaid_settings/test_plaid_settings.py b/erpnext/erpnext_integrations/doctype/plaid_settings/test_plaid_settings.py
index 29e8fa4..1a063d6 100644
--- a/erpnext/erpnext_integrations/doctype/plaid_settings/test_plaid_settings.py
+++ b/erpnext/erpnext_integrations/doctype/plaid_settings/test_plaid_settings.py
@@ -23,11 +23,11 @@
 		for ba in frappe.get_all("Bank Account"):
 			frappe.get_doc("Bank Account", ba.name).delete()
 
-		for at in frappe.get_all("Account Type"):
-			frappe.get_doc("Account Type", at.name).delete()
+		for at in frappe.get_all("Bank Account Type"):
+			frappe.get_doc("Bank Account Type", at.name).delete()
 
-		for ast in frappe.get_all("Account Subtype"):
-			frappe.get_doc("Account Subtype", ast.name).delete()
+		for ast in frappe.get_all("Bank Account Subtype"):
+			frappe.get_doc("Bank Account Subtype", ast.name).delete()
 
 	def test_plaid_disabled(self):
 		frappe.db.set_value("Plaid Settings", None, "enabled", 0)
@@ -35,11 +35,11 @@
 
 	def test_add_account_type(self):
 		add_account_type("brokerage")
-		self.assertEqual(frappe.get_doc("Account Type", "brokerage").name, "brokerage")
+		self.assertEqual(frappe.get_doc("Bank Account Type", "brokerage").name, "brokerage")
 
 	def test_add_account_subtype(self):
 		add_account_subtype("loan")
-		self.assertEqual(frappe.get_doc("Account Subtype", "loan").name, "loan")
+		self.assertEqual(frappe.get_doc("Bank Account Subtype", "loan").name, "loan")
 
 	def test_default_bank_account(self):
 		if not frappe.db.exists("Bank", "Citi"):
diff --git a/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.js b/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.js
index 5f36bdd..87c22cc 100644
--- a/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.js
+++ b/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.js
@@ -80,6 +80,7 @@
 							frappe.call({
 								method: 'complete_procedure',
 								doc: frm.doc,
+								freeze: true,
 								callback: function(r) {
 									if (r.message) {
 										frappe.show_alert({
@@ -87,8 +88,8 @@
 												['<a class="bold" href="#Form/Stock Entry/'+ r.message + '">' + r.message + '</a>']),
 											indicator: 'green'
 										});
-										frm.reload_doc();
 									}
+									frm.reload_doc();
 								}
 							});
 						}
@@ -111,9 +112,10 @@
 											frappe.call({
 												doc: frm.doc,
 												method: 'make_material_receipt',
+												freeze: true,
 												callback: function(r) {
 													if (!r.exc) {
-														cur_frm.reload_doc();
+														frm.reload_doc();
 														let doclist = frappe.model.sync(r.message);
 														frappe.set_route('Form', doclist[0].doctype, doclist[0].name);
 													}
@@ -122,7 +124,7 @@
 										}
 									);
 								} else {
-									cur_frm.reload_doc();
+									frm.reload_doc();
 								}
 							}
 						}
diff --git a/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.py b/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.py
index db3afc8..b7d7a62 100644
--- a/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.py
+++ b/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.py
@@ -87,7 +87,8 @@
 			else:
 				frappe.throw(_('Please set Customer in Patient {0}').format(frappe.bold(self.patient)), title=_('Customer Not Found'))
 
-		frappe.db.set_value('Clinical Procedure', self.name, 'status', 'Completed')
+		self.db_set('status', 'Completed')
+
 		if self.consume_stock and self.items:
 			return stock_entry
 
@@ -245,9 +246,9 @@
 
 
 def insert_clinical_procedure_to_medical_record(doc):
-	subject = cstr(doc.procedure_template)
+	subject = frappe.bold(_("Clinical Procedure conducted: ")) + cstr(doc.procedure_template) + "<br>"
 	if doc.practitioner:
-		subject += ' ' + doc.practitioner
+		subject += frappe.bold(_('Healthcare Practitioner: ')) + doc.practitioner
 	if subject and doc.notes:
 		subject += '<br/>' + doc.notes
 
diff --git a/erpnext/healthcare/doctype/exercise_type/exercise_type.js b/erpnext/healthcare/doctype/exercise_type/exercise_type.js
index f450c9b..68db047 100644
--- a/erpnext/healthcare/doctype/exercise_type/exercise_type.js
+++ b/erpnext/healthcare/doctype/exercise_type/exercise_type.js
@@ -24,6 +24,8 @@
 
 		this.exercise_cards = $('<div class="exercise-cards"></div>').appendTo(this.wrapper);
 
+		this.row = $('<div class="exercise-row"></div>').appendTo(this.wrapper);
+
 		let me = this;
 
 		this.exercise_toolbar.find(".btn-add")
@@ -32,7 +34,7 @@
 				me.show_add_card_dialog(frm);
 			});
 
-		if (frm.doc.steps_table.length > 0) {
+		if (frm.doc.steps_table && frm.doc.steps_table.length > 0) {
 			this.make_cards(frm);
 			this.make_buttons(frm);
 		}
@@ -41,7 +43,6 @@
 	make_cards: function(frm) {
 		var me = this;
 		$(me.exercise_cards).empty();
-		this.row = $('<div class="exercise-row"></div>').appendTo(me.exercise_cards);
 
 		$.each(frm.doc.steps_table, function(i, step) {
 			$(repl(`
@@ -78,6 +79,7 @@
 				frm.doc.steps_table.pop(id);
 				frm.refresh_field('steps_table');
 				$('#col-'+id).remove();
+				frm.dirty();
 			}, 300);
 		});
 	},
@@ -106,7 +108,10 @@
 			],
 			primary_action: function() {
 				let data = d.get_values();
-				let i = frm.doc.steps_table.length;
+				let i = 0;
+				if (frm.doc.steps_table) {
+					i = frm.doc.steps_table.length;
+				}
 				$(repl(`
 					<div class="exercise-col col-sm-4" id="%(col_id)s">
 						<div class="card h-100 exercise-card" id="%(card_id)s">
@@ -165,9 +170,10 @@
 				frm.doc.steps_table[id].image = data.image;
 				frm.doc.steps_table[id].description = data.step_description;
 				refresh_field('steps_table');
+				frm.dirty();
 				new_dialog.hide();
 			},
-			primary_action_label: __("Save"),
+			primary_action_label: __("Edit"),
 		});
 
 		new_dialog.set_values({
diff --git a/erpnext/healthcare/doctype/lab_test/lab_test.py b/erpnext/healthcare/doctype/lab_test/lab_test.py
index 4e4015d..ea8ce25 100644
--- a/erpnext/healthcare/doctype/lab_test/lab_test.py
+++ b/erpnext/healthcare/doctype/lab_test/lab_test.py
@@ -288,23 +288,23 @@
 	table_row = False
 	subject = cstr(doc.lab_test_name)
 	if doc.practitioner:
-		subject += " "+ doc.practitioner
+		subject += frappe.bold(_("Healthcare Practitioner: "))+ doc.practitioner + "<br>"
 	if doc.normal_test_items:
 		item = doc.normal_test_items[0]
 		comment = ""
 		if item.lab_test_comment:
 			comment = str(item.lab_test_comment)
-		table_row = item.lab_test_name
+		table_row = frappe.bold(_("Lab Test Conducted: ")) + item.lab_test_name
 
 		if item.lab_test_event:
-			table_row += " " + item.lab_test_event
+			table_row += frappe.bold(_("Lab Test Event: ")) + item.lab_test_event
 
 		if item.result_value:
-			table_row += " " + item.result_value
+			table_row += " " + frappe.bold(_("Lab Test Result: ")) + item.result_value
 
 		if item.normal_range:
-			table_row += " normal_range("+item.normal_range+")"
-		table_row += " "+comment
+			table_row += " " + _("Normal Range:") + item.normal_range
+		table_row += " " + comment
 
 	elif doc.special_test_items:
 		item = doc.special_test_items[0]
@@ -316,12 +316,12 @@
 		item = doc.sensitivity_test_items[0]
 
 		if item.antibiotic and item.antibiotic_sensitivity:
-			table_row = item.antibiotic +" "+ item.antibiotic_sensitivity
+			table_row = item.antibiotic + " " + item.antibiotic_sensitivity
 
 	if table_row:
-		subject += "<br/>"+table_row
+		subject += "<br>" + table_row
 	if doc.lab_test_comment:
-		subject += "<br/>"+ cstr(doc.lab_test_comment)
+		subject += "<br>" + cstr(doc.lab_test_comment)
 
 	medical_record = frappe.new_doc("Patient Medical Record")
 	medical_record.patient = doc.patient
diff --git a/erpnext/healthcare/doctype/patient_encounter/patient_encounter.py b/erpnext/healthcare/doctype/patient_encounter/patient_encounter.py
index 767643b..1734c28 100644
--- a/erpnext/healthcare/doctype/patient_encounter/patient_encounter.py
+++ b/erpnext/healthcare/doctype/patient_encounter/patient_encounter.py
@@ -18,6 +18,9 @@
 	def after_insert(self):
 		insert_encounter_to_medical_record(self)
 
+	def on_submit(self):
+		update_encounter_medical_record(self)
+
 	def on_cancel(self):
 		if self.appointment:
 			frappe.db.set_value('Patient Appointment', self.appointment, 'status', 'Open')
@@ -66,22 +69,26 @@
 	frappe.db.delete_doc_if_exists('Patient Medical Record', 'reference_name', encounter.name)
 
 def set_subject_field(encounter):
-	subject = encounter.practitioner + '\n'
+	subject = frappe.bold(_('Healthcare Practitioner: ')) + encounter.practitioner + '<br>'
 	if encounter.symptoms:
-		subject += _('Symptoms: ') + cstr(encounter.symptoms) + '\n'
+		subject += frappe.bold(_('Symptoms: ')) + '<br>'
+		for entry in encounter.symptoms:
+			subject += cstr(entry.complaint) + '<br>'
 	else:
-		subject +=  _('No Symptoms') + '\n'
+		subject += frappe.bold(_('No Symptoms')) + '<br>'
 
 	if encounter.diagnosis:
-		subject += _('Diagnosis: ') + cstr(encounter.diagnosis) + '\n'
+		subject += frappe.bold(_('Diagnosis: ')) + '<br>'
+		for entry in encounter.diagnosis:
+			subject += cstr(entry.diagnosis) + '<br>'
 	else:
-		subject += _('No Diagnosis') + '\n'
+		subject += frappe.bold(_('No Diagnosis')) + '<br>'
 
 	if encounter.drug_prescription:
-		subject += '\n' + _('Drug(s) Prescribed.')
+		subject += '<br>' + _('Drug(s) Prescribed.')
 	if encounter.lab_test_prescription:
-		subject += '\n' + _('Test(s) Prescribed.')
+		subject += '<br>' + _('Test(s) Prescribed.')
 	if encounter.procedure_prescription:
-		subject += '\n' + _('Procedure(s) Prescribed.')
+		subject += '<br>' + _('Procedure(s) Prescribed.')
 
 	return subject
diff --git a/erpnext/healthcare/doctype/patient_medical_record/patient_medical_record.json b/erpnext/healthcare/doctype/patient_medical_record/patient_medical_record.json
index 3655e24..ed82355 100644
--- a/erpnext/healthcare/doctype/patient_medical_record/patient_medical_record.json
+++ b/erpnext/healthcare/doctype/patient_medical_record/patient_medical_record.json
@@ -57,7 +57,7 @@
   },
   {
    "fieldname": "subject",
-   "fieldtype": "Small Text",
+   "fieldtype": "Text Editor",
    "ignore_xss_filter": 1,
    "label": "Subject"
   },
@@ -125,7 +125,7 @@
  ],
  "in_create": 1,
  "links": [],
- "modified": "2020-03-23 19:26:59.308383",
+ "modified": "2020-04-29 12:26:57.679402",
  "modified_by": "Administrator",
  "module": "Healthcare",
  "name": "Patient Medical Record",
diff --git a/erpnext/healthcare/doctype/therapy_plan/therapy_plan.py b/erpnext/healthcare/doctype/therapy_plan/therapy_plan.py
index 201264f..c19be17 100644
--- a/erpnext/healthcare/doctype/therapy_plan/therapy_plan.py
+++ b/erpnext/healthcare/doctype/therapy_plan/therapy_plan.py
@@ -21,8 +21,14 @@
 				self.status = 'Completed'
 
 	def set_totals(self):
-		total_sessions = sum([int(d.no_of_sessions) for d in self.get('therapy_plan_details')])
-		total_sessions_completed = sum([int(d.sessions_completed) for d in self.get('therapy_plan_details')])
+		total_sessions = 0
+		total_sessions_completed = 0
+		for entry in self.therapy_plan_details:
+			if entry.no_of_sessions:
+				total_sessions += entry.no_of_sessions
+			if entry.sessions_completed:
+				total_sessions_completed += entry.sessions_completed
+
 		self.db_set('total_sessions', total_sessions)
 		self.db_set('total_sessions_completed', total_sessions_completed)
 
diff --git a/erpnext/healthcare/doctype/therapy_session/therapy_session.js b/erpnext/healthcare/doctype/therapy_session/therapy_session.js
index bb67575..abe4def 100644
--- a/erpnext/healthcare/doctype/therapy_session/therapy_session.js
+++ b/erpnext/healthcare/doctype/therapy_session/therapy_session.js
@@ -13,23 +13,92 @@
 
 	refresh: function(frm) {
 		if (!frm.doc.__islocal) {
-			let target = 0;
-			let completed = 0;
-			$.each(frm.doc.exercises, function(_i, e) {
-				target += e.counts_target;
-				completed += e.counts_completed;
-			});
-			frm.dashboard.add_indicator(__('Counts Targetted: {0}', [target]), 'blue');
-			frm.dashboard.add_indicator(__('Counts Completed: {0}', [completed]), (completed < target) ? 'orange' : 'green');
+			frm.dashboard.add_indicator(__('Counts Targeted: {0}', [frm.doc.total_counts_targeted]), 'blue');
+			frm.dashboard.add_indicator(__('Counts Completed: {0}', [frm.doc.total_counts_completed]),
+				(frm.doc.total_counts_completed < frm.doc.total_counts_targeted) ? 'orange' : 'green');
 		}
 
 		if (frm.doc.docstatus === 1) {
-			frm.add_custom_button(__('Patient Assessment'),function() {
+			frm.add_custom_button(__('Patient Assessment'), function() {
 				frappe.model.open_mapped_doc({
 					method: 'erpnext.healthcare.doctype.patient_assessment.patient_assessment.create_patient_assessment',
 					frm: frm,
 				})
 			}, 'Create');
+
+			frm.add_custom_button(__('Sales Invoice'), function() {
+				frappe.model.open_mapped_doc({
+					method: 'erpnext.healthcare.doctype.therapy_session.therapy_session.invoice_therapy_session',
+					frm: frm,
+				})
+			}, 'Create');
+		}
+	},
+
+	patient: function(frm) {
+		if (frm.doc.patient) {
+			frappe.call({
+				'method': 'erpnext.healthcare.doctype.patient.patient.get_patient_detail',
+				args: {
+					patient: frm.doc.patient
+				},
+				callback: function (data) {
+					let age = '';
+					if (data.message.dob) {
+						age = calculate_age(data.message.dob);
+					} else if (data.message.age) {
+						age = data.message.age;
+						if (data.message.age_as_on) {
+							age = __('{0} as on {1}', [age, data.message.age_as_on]);
+						}
+					}
+					frm.set_value('patient_age', age);
+					frm.set_value('gender', data.message.sex);
+					frm.set_value('patient_name', data.message.patient_name);
+				}
+			});
+		} else {
+			frm.set_value('patient_age', '');
+			frm.set_value('gender', '');
+			frm.set_value('patient_name', '');
+		}
+	},
+
+	appointment: function(frm) {
+		if (frm.doc.appointment) {
+			frappe.call({
+				'method': 'frappe.client.get',
+				args: {
+					doctype: 'Patient Appointment',
+					name: frm.doc.appointment
+				},
+				callback: function(data) {
+					let values = {
+						'patient':data.message.patient,
+						'therapy_type': data.message.therapy_type,
+						'therapy_plan': data.message.therapy_plan,
+						'practitioner': data.message.practitioner,
+						'department': data.message.department,
+						'start_date': data.message.appointment_date,
+						'start_time': data.message.appointment_time,
+						'service_unit': data.message.service_unit,
+						'company': data.message.company
+					};
+					frm.set_value(values);
+				}
+			});
+		} else {
+			let values = {
+				'patient': '',
+				'therapy_type': '',
+				'therapy_plan': '',
+				'practitioner': '',
+				'department': '',
+				'start_date': '',
+				'start_time': '',
+				'service_unit': '',
+			};
+			frm.set_value(values);
 		}
 	},
 
@@ -44,6 +113,8 @@
 				callback: function(data) {
 					frm.set_value('duration', data.message.default_duration);
 					frm.set_value('rate', data.message.rate);
+					frm.set_value('service_unit', data.message.healthcare_service_unit);
+					frm.set_value('department', data.message.medical_department);
 					frm.doc.exercises = [];
 					$.each(data.message.exercises, function(_i, e) {
 						let exercise = frm.add_child('exercises');
diff --git a/erpnext/healthcare/doctype/therapy_session/therapy_session.json b/erpnext/healthcare/doctype/therapy_session/therapy_session.json
index 5ff7196..00d74a0 100644
--- a/erpnext/healthcare/doctype/therapy_session/therapy_session.json
+++ b/erpnext/healthcare/doctype/therapy_session/therapy_session.json
@@ -9,9 +9,11 @@
   "naming_series",
   "appointment",
   "patient",
+  "patient_name",
   "patient_age",
   "gender",
   "column_break_5",
+  "company",
   "therapy_plan",
   "therapy_type",
   "practitioner",
@@ -20,7 +22,6 @@
   "duration",
   "rate",
   "location",
-  "company",
   "column_break_12",
   "service_unit",
   "start_date",
@@ -28,6 +29,10 @@
   "invoiced",
   "exercises_section",
   "exercises",
+  "section_break_23",
+  "total_counts_targeted",
+  "column_break_25",
+  "total_counts_completed",
   "amended_from"
  ],
  "fields": [
@@ -159,7 +164,8 @@
    "fieldname": "company",
    "fieldtype": "Link",
    "label": "Company",
-   "options": "Company"
+   "options": "Company",
+   "reqd": 1
   },
   {
    "default": "0",
@@ -173,11 +179,38 @@
    "fieldtype": "Data",
    "label": "Patient Age",
    "read_only": 1
+  },
+  {
+   "fieldname": "total_counts_targeted",
+   "fieldtype": "Int",
+   "label": "Total Counts Targeted",
+   "read_only": 1
+  },
+  {
+   "fieldname": "total_counts_completed",
+   "fieldtype": "Int",
+   "label": "Total Counts Completed",
+   "read_only": 1
+  },
+  {
+   "fieldname": "section_break_23",
+   "fieldtype": "Section Break"
+  },
+  {
+   "fieldname": "column_break_25",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fetch_from": "patient.patient_name",
+   "fieldname": "patient_name",
+   "fieldtype": "Data",
+   "label": "Patient Name",
+   "read_only": 1
   }
  ],
  "is_submittable": 1,
  "links": [],
- "modified": "2020-04-21 13:16:46.378798",
+ "modified": "2020-04-29 16:49:16.286006",
  "modified_by": "Administrator",
  "module": "Healthcare",
  "name": "Therapy Session",
diff --git a/erpnext/healthcare/doctype/therapy_session/therapy_session.py b/erpnext/healthcare/doctype/therapy_session/therapy_session.py
index 45d2ee6..9650183 100644
--- a/erpnext/healthcare/doctype/therapy_session/therapy_session.py
+++ b/erpnext/healthcare/doctype/therapy_session/therapy_session.py
@@ -6,10 +6,17 @@
 import frappe
 from frappe.model.document import Document
 from frappe.model.mapper import get_mapped_doc
+from frappe import _
+from frappe.utils import cstr, getdate
+from erpnext.healthcare.doctype.healthcare_settings.healthcare_settings import get_receivable_account, get_income_account
 
 class TherapySession(Document):
+	def validate(self):
+		self.set_total_counts()
+
 	def on_submit(self):
 		self.update_sessions_count_in_therapy_plan()
+		insert_session_medical_record(self)
 
 	def on_cancel(self):
 		self.update_sessions_count_in_therapy_plan(on_cancel=True)
@@ -24,6 +31,18 @@
 					entry.sessions_completed += 1
 		therapy_plan.save()
 
+	def set_total_counts(self):
+		target_total = 0
+		counts_completed = 0
+		for entry in self.exercises:
+			if entry.counts_target:
+				target_total += entry.counts_target
+			if entry.counts_completed:
+				counts_completed += entry.counts_completed
+
+		self.db_set('total_counts_targeted', target_total)
+		self.db_set('total_counts_completed', counts_completed)
+
 
 @frappe.whitelist()
 def create_therapy_session(source_name, target_doc=None):
@@ -52,4 +71,62 @@
 			}
 		}, target_doc, set_missing_values)
 
-	return doc
\ No newline at end of file
+	return doc
+
+
+@frappe.whitelist()
+def invoice_therapy_session(source_name, target_doc=None):
+	def set_missing_values(source, target):
+		target.customer = frappe.db.get_value('Patient', source.patient, 'customer')
+		target.due_date = getdate()
+		target.debit_to = get_receivable_account(source.company)
+		item = target.append('items', {})
+		item = get_therapy_item(source, item)
+		target.set_missing_values(for_validate=True)
+
+	doc = get_mapped_doc('Therapy Session', source_name, {
+			'Therapy Session': {
+				'doctype': 'Sales Invoice',
+				'field_map': [
+					['patient', 'patient'],
+					['referring_practitioner', 'practitioner'],
+					['company', 'company'],
+					['due_date', 'start_date']
+				]
+			}
+		}, target_doc, set_missing_values)
+
+	return doc
+
+
+def get_therapy_item(therapy, item):
+	item.item_code = frappe.db.get_value('Therapy Type', therapy.therapy_type, 'item')
+	item.description = _('Therapy Session Charges: {0}').format(therapy.practitioner)
+	item.income_account = get_income_account(therapy.practitioner, therapy.company)
+	item.cost_center = frappe.get_cached_value('Company', therapy.company, 'cost_center')
+	item.rate = therapy.rate
+	item.amount = therapy.rate
+	item.qty = 1
+	item.reference_dt = 'Therapy Session'
+	item.reference_dn = therapy.name
+	return item
+
+
+def insert_session_medical_record(doc):
+	subject = frappe.bold(_('Therapy: ')) + cstr(doc.therapy_type) + '<br>'
+	if doc.therapy_plan:
+		subject += frappe.bold(_('Therapy Plan: ')) + cstr(doc.therapy_plan) + '<br>'
+	if doc.practitioner:
+		subject += frappe.bold(_('Healthcare Practitioner: ')) + doc.practitioner
+	subject += frappe.bold(_('Total Counts Targeted: ')) + cstr(doc.total_counts_targeted) + '<br>'
+	subject += frappe.bold(_('Total Counts Completed: ')) + cstr(doc.total_counts_completed) + '<br>'
+
+	medical_record = frappe.new_doc('Patient Medical Record')
+	medical_record.patient = doc.patient
+	medical_record.subject = subject
+	medical_record.status = 'Open'
+	medical_record.communication_date = doc.start_date
+	medical_record.reference_doctype = 'Therapy Session'
+	medical_record.reference_name = doc.name
+	medical_record.reference_owner = doc.owner
+	medical_record.save(ignore_permissions=True)
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/vital_signs/vital_signs.py b/erpnext/healthcare/doctype/vital_signs/vital_signs.py
index 959e850..b0e78e8 100644
--- a/erpnext/healthcare/doctype/vital_signs/vital_signs.py
+++ b/erpnext/healthcare/doctype/vital_signs/vital_signs.py
@@ -35,17 +35,17 @@
 
 def set_subject_field(doc):
 	subject = ''
-	if(doc.temperature):
-		subject += _('Temperature: ') + '\n'+ cstr(doc.temperature) + '. '
-	if(doc.pulse):
-		subject += _('Pulse: ') + '\n' + cstr(doc.pulse) + '. '
-	if(doc.respiratory_rate):
-		subject += _('Respiratory Rate: ') + '\n' + cstr(doc.respiratory_rate) + '. '
-	if(doc.bp):
-		subject += _('BP: ') + '\n' + cstr(doc.bp) + '. '
-	if(doc.bmi):
-		subject += _('BMI: ') + '\n' + cstr(doc.bmi) + '. '
-	if(doc.nutrition_note):
-		subject += _('Note: ') + '\n' + cstr(doc.nutrition_note) + '. '
+	if doc.temperature:
+		subject += frappe.bold(_('Temperature: ')) + cstr(doc.temperature) + '<br>'
+	if doc.pulse:
+		subject += frappe.bold(_('Pulse: ')) + cstr(doc.pulse) + '<br>'
+	if doc.respiratory_rate:
+		subject += frappe.bold(_('Respiratory Rate: ')) + cstr(doc.respiratory_rate) + '<br>'
+	if doc.bp:
+		subject += frappe.bold(_('BP: ')) + cstr(doc.bp) + '<br>'
+	if doc.bmi:
+		subject += frappe.bold(_('BMI: ')) + cstr(doc.bmi) + '<br>'
+	if doc.nutrition_note:
+		subject += frappe.bold(_('Note: ')) + cstr(doc.nutrition_note) + '<br>'
 
 	return subject
diff --git a/erpnext/healthcare/utils.py b/erpnext/healthcare/utils.py
index 9a32c73..a756532 100644
--- a/erpnext/healthcare/utils.py
+++ b/erpnext/healthcare/utils.py
@@ -43,7 +43,7 @@
 
 def get_fee_validity(patient_appointments):
 	if not frappe.db.get_single_value('Healthcare Settings', 'enable_free_follow_ups'):
-		return
+		return []
 
 	items_to_invoice = []
 	for appointment in patient_appointments:
@@ -110,7 +110,7 @@
 		filters={'patient': patient.name, 'invoiced': False, 'docstatus': 1}
 	)
 	for lab_test in lab_tests:
-		item, is_billable = frappe.get_cached_value('Lab Test Template', lab_test.lab_test_code, ['item', 'is_billable'])
+		item, is_billable = frappe.get_cached_value('Lab Test Template', lab_test.template, ['item', 'is_billable'])
 		if is_billable:
 			lab_tests_to_invoice.append({
 				'reference_type': 'Lab Test',
diff --git a/erpnext/hooks.py b/erpnext/hooks.py
index 6b6d1e2..6b198e7 100644
--- a/erpnext/hooks.py
+++ b/erpnext/hooks.py
@@ -250,7 +250,8 @@
 	},
 	"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.communication.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"
@@ -270,7 +271,8 @@
 scheduler_events = {
 	"all": [
 		"erpnext.projects.doctype.project.project.project_status_update_reminder",
-		"erpnext.healthcare_healthcare.doctype.patient_appointment.patient_appointment.send_appointment_reminder"
+		"erpnext.healthcare.doctype.patient_appointment.patient_appointment.send_appointment_reminder",
+		"erpnext.crm.doctype.social_media_post.social_media_post.process_scheduled_social_media_posts"
 	],
 	"hourly": [
 		'erpnext.hr.doctype.daily_work_summary_group.daily_work_summary_group.trigger_emails',
@@ -536,4 +538,4 @@
 		{'doctype': 'Hotel Room Package', 'index': 3},
 		{'doctype': 'Hotel Room Type', 'index': 4}
 	]
-}
\ No newline at end of file
+}
diff --git a/erpnext/hr/desk_page/hr/hr.json b/erpnext/hr/desk_page/hr/hr.json
index 743aa23..22aa170 100644
--- a/erpnext/hr/desk_page/hr/hr.json
+++ b/erpnext/hr/desk_page/hr/hr.json
@@ -23,7 +23,7 @@
   {
    "hidden": 0,
    "label": "Payroll",
-   "links": "[\n    {\n        \"label\": \"Salary Structure\",\n        \"name\": \"Salary Structure\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n    },\n    {\n        \"dependencies\": [\n            \"Salary Structure\",\n            \"Employee\"\n        ],\n        \"label\": \"Salary Structure Assignment\",\n        \"name\": \"Salary Structure Assignment\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"Payroll Entry\",\n        \"name\": \"Payroll Entry\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"Salary Slip\",\n        \"name\": \"Salary Slip\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"Payroll Period\",\n        \"name\": \"Payroll Period\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"Salary Component\",\n        \"name\": \"Salary Component\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"Additional Salary\",\n        \"name\": \"Additional Salary\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"dependencies\": [\n            \"Employee\"\n        ],\n        \"label\": \"Retention Bonus\",\n        \"name\": \"Retention Bonus\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"dependencies\": [\n            \"Employee\"\n        ],\n        \"label\": \"Employee Incentive\",\n        \"name\": \"Employee Incentive\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"dependencies\": [\n            \"Salary Slip\"\n        ],\n        \"doctype\": \"Salary Slip\",\n        \"is_query_report\": true,\n        \"label\": \"Salary Register\",\n        \"name\": \"Salary Register\",\n        \"type\": \"report\"\n    }\n]"
+   "links": "[\n    {\n        \"label\": \"Salary Structure\",\n        \"name\": \"Salary Structure\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n    },\n    {\n        \"dependencies\": [\n            \"Salary Structure\",\n            \"Employee\"\n        ],\n        \"label\": \"Salary Structure Assignment\",\n        \"name\": \"Salary Structure Assignment\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"Payroll Entry\",\n        \"name\": \"Payroll Entry\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"Salary Slip\",\n        \"name\": \"Salary Slip\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"Payroll Period\",\n        \"name\": \"Payroll Period\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"Income Tax Slab\",\n        \"name\": \"Income Tax Slab\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"Salary Component\",\n        \"name\": \"Salary Component\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"Additional Salary\",\n        \"name\": \"Additional Salary\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"dependencies\": [\n            \"Employee\"\n        ],\n        \"label\": \"Retention Bonus\",\n        \"name\": \"Retention Bonus\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"dependencies\": [\n            \"Employee\"\n        ],\n        \"label\": \"Employee Incentive\",\n        \"name\": \"Employee Incentive\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"dependencies\": [\n            \"Salary Slip\"\n        ],\n        \"doctype\": \"Salary Slip\",\n        \"is_query_report\": true,\n        \"label\": \"Salary Register\",\n        \"name\": \"Salary Register\",\n        \"type\": \"report\"\n    }\n]"
   },
   {
    "hidden": 0,
@@ -73,7 +73,7 @@
   {
    "hidden": 0,
    "label": "Employee Tax and Benefits",
-   "links": "[\n    {\n        \"dependencies\": [\n            \"Employee\"\n        ],\n        \"label\": \"Employee Tax Exemption Declaration\",\n        \"name\": \"Employee Tax Exemption Declaration\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"dependencies\": [\n            \"Employee\"\n        ],\n        \"label\": \"Employee Tax Exemption Proof Submission\",\n        \"name\": \"Employee Tax Exemption Proof Submission\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"dependencies\": [\n            \"Employee\"\n        ],\n        \"label\": \"Employee Benefit Application\",\n        \"name\": \"Employee Benefit Application\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"dependencies\": [\n            \"Employee\"\n        ],\n        \"label\": \"Employee Benefit Claim\",\n        \"name\": \"Employee Benefit Claim\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"dependencies\": [\n            \"Employee\"\n        ],\n        \"label\": \"Employee Tax Exemption Category\",\n        \"name\": \"Employee Tax Exemption Category\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"dependencies\": [\n            \"Employee\"\n        ],\n        \"label\": \"Employee Tax Exemption Sub Category\",\n        \"name\": \"Employee Tax Exemption Sub Category\",\n        \"type\": \"doctype\"\n    }\n]"
+   "links": "[\n    {\n        \"dependencies\": [\n            \"Employee\"\n        ],\n        \"label\": \"Employee Tax Exemption Declaration\",\n        \"name\": \"Employee Tax Exemption Declaration\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"dependencies\": [\n            \"Employee\"\n        ],\n        \"label\": \"Employee Tax Exemption Proof Submission\",\n        \"name\": \"Employee Tax Exemption Proof Submission\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"dependencies\": [\n            \"Employee\",\n            \"Payroll Period\"\n        ],\n        \"label\": \"Employee Other Income\",\n        \"name\": \"Employee Other Income\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"dependencies\": [\n            \"Employee\"\n        ],\n        \"label\": \"Employee Benefit Application\",\n        \"name\": \"Employee Benefit Application\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"dependencies\": [\n            \"Employee\"\n        ],\n        \"label\": \"Employee Benefit Claim\",\n        \"name\": \"Employee Benefit Claim\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"dependencies\": [\n            \"Employee\"\n        ],\n        \"label\": \"Employee Tax Exemption Category\",\n        \"name\": \"Employee Tax Exemption Category\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"dependencies\": [\n            \"Employee\"\n        ],\n        \"label\": \"Employee Tax Exemption Sub Category\",\n        \"name\": \"Employee Tax Exemption Sub Category\",\n        \"type\": \"doctype\"\n    }\n]"
   }
  ],
  "category": "Modules",
@@ -88,7 +88,7 @@
  "idx": 0,
  "is_standard": 1,
  "label": "HR",
- "modified": "2020-04-01 11:28:50.860012",
+ "modified": "2020-04-29 20:29:22.114309",
  "modified_by": "Administrator",
  "module": "HR",
  "name": "HR",
diff --git a/erpnext/hr/doctype/attendance/attendance.json b/erpnext/hr/doctype/attendance/attendance.json
index eaca9f6..906f6f7 100644
--- a/erpnext/hr/doctype/attendance/attendance.json
+++ b/erpnext/hr/doctype/attendance/attendance.json
@@ -87,11 +87,12 @@
    "search_index": 1
   },
   {
-   "depends_on": "eval:doc.status==\"On Leave\"",
+   "depends_on": "eval:in_list([\"On Leave\", \"Half Day\"], doc.status)",
    "fieldname": "leave_type",
    "fieldtype": "Link",
    "in_standard_filter": 1,
    "label": "Leave Type",
+   "mandatory_depends_on": "eval:in_list([\"On Leave\", \"Half Day\"], doc.status)",
    "oldfieldname": "leave_type",
    "oldfieldtype": "Link",
    "options": "Leave Type"
@@ -100,6 +101,7 @@
    "fieldname": "leave_application",
    "fieldtype": "Link",
    "label": "Leave Application",
+   "no_copy": 1,
    "options": "Leave Application",
    "read_only": 1
   },
@@ -175,7 +177,8 @@
  "icon": "fa fa-ok",
  "idx": 1,
  "is_submittable": 1,
- "modified": "2020-02-19 14:25:32.945842",
+ "links": [],
+ "modified": "2020-04-11 11:40:14.319496",
  "modified_by": "Administrator",
  "module": "HR",
  "name": "Attendance",
diff --git a/erpnext/hr/doctype/attendance/attendance.py b/erpnext/hr/doctype/attendance/attendance.py
index 9e965db..b6c8065 100644
--- a/erpnext/hr/doctype/attendance/attendance.py
+++ b/erpnext/hr/doctype/attendance/attendance.py
@@ -7,33 +7,15 @@
 from frappe.utils import getdate, nowdate
 from frappe import _
 from frappe.model.document import Document
-from frappe.utils import cstr, get_datetime, get_datetime_str
-from frappe.utils import update_progress_bar
+from frappe.utils import cstr, get_datetime, formatdate
 
 class Attendance(Document):
-	def validate_duplicate_record(self):
-		res = frappe.db.sql("""select name from `tabAttendance` where employee = %s and attendance_date = %s
-			and name != %s and docstatus != 2""",
-			(self.employee, getdate(self.attendance_date), self.name))
-		if res:
-			frappe.throw(_("Attendance for employee {0} is already marked").format(self.employee))
-
-	def check_leave_record(self):
-		leave_record = frappe.db.sql("""select leave_type, half_day, half_day_date from `tabLeave Application`
-			where employee = %s and %s between from_date and to_date and status = 'Approved'
-			and docstatus = 1""", (self.employee, self.attendance_date), as_dict=True)
-		if leave_record:
-			for d in leave_record:
-				if d.half_day_date == getdate(self.attendance_date):
-					self.status = 'Half Day'
-					frappe.msgprint(_("Employee {0} on Half day on {1}").format(self.employee, self.attendance_date))
-				else:
-					self.status = 'On Leave'
-					self.leave_type = d.leave_type
-					frappe.msgprint(_("Employee {0} is on Leave on {1}").format(self.employee, self.attendance_date))
-
-		if self.status == "On Leave" and not leave_record:
-			frappe.throw(_("No leave record found for employee {0} for {1}").format(self.employee, self.attendance_date))
+	def validate(self):
+		from erpnext.controllers.status_updater import validate_status
+		validate_status(self.status, ["Present", "Absent", "On Leave", "Half Day", "Work From Home"])
+		self.validate_attendance_date()
+		self.validate_duplicate_record()
+		self.check_leave_record()
 
 	def validate_attendance_date(self):
 		date_of_joining = frappe.db.get_value("Employee", self.employee, "date_of_joining")
@@ -44,19 +26,52 @@
 		elif date_of_joining and getdate(self.attendance_date) < getdate(date_of_joining):
 			frappe.throw(_("Attendance date can not be less than employee's joining date"))
 
+	def validate_duplicate_record(self):
+		res = frappe.db.sql("""
+			select name from `tabAttendance`
+			where employee = %s
+				and attendance_date = %s
+				and name != %s
+				and docstatus != 2
+		""", (self.employee, getdate(self.attendance_date), self.name))
+		if res:
+			frappe.throw(_("Attendance for employee {0} is already marked").format(self.employee))
+
+	def check_leave_record(self):
+		leave_record = frappe.db.sql("""
+			select leave_type, half_day, half_day_date
+			from `tabLeave Application`
+			where employee = %s 
+				and %s between from_date and to_date
+				and status = 'Approved'
+				and docstatus = 1
+		""", (self.employee, self.attendance_date), as_dict=True)
+		if leave_record:
+			for d in leave_record:
+				self.leave_type = d.leave_type
+				if d.half_day_date == getdate(self.attendance_date):
+					self.status = 'Half Day'
+					frappe.msgprint(_("Employee {0} on Half day on {1}")
+						.format(self.employee, formatdate(self.attendance_date)))
+				else:
+					self.status = 'On Leave'
+					frappe.msgprint(_("Employee {0} is on Leave on {1}")
+						.format(self.employee, formatdate(self.attendance_date)))
+
+		if self.status in ("On Leave", "Half Day"):
+			if not leave_record:
+				frappe.msgprint(_("No leave record found for employee {0} on {1}")
+					.format(self.employee, formatdate(self.attendance_date)), alert=1)
+		elif self.leave_type:
+			self.leave_type = None
+			self.leave_application = None
+
 	def validate_employee(self):
 		emp = frappe.db.sql("select name from `tabEmployee` where name = %s and status = 'Active'",
 		 	self.employee)
 		if not emp:
 			frappe.throw(_("Employee {0} is not active or does not exist").format(self.employee))
 
-	def validate(self):
-		from erpnext.controllers.status_updater import validate_status
-		validate_status(self.status, ["Present", "Absent", "On Leave", "Half Day", "Work From Home"])
-		self.validate_attendance_date()
-		self.validate_duplicate_record()
-		self.check_leave_record()
-
 @frappe.whitelist()
 def get_events(start, end, filters=None):
 	events = []
@@ -90,18 +105,20 @@
 		if e not in events:
 			events.append(e)
 
-def mark_attendance(employee, attendance_date, status, shift=None):
-	employee_doc = frappe.get_doc('Employee', employee)
+def mark_attendance(employee, attendance_date, status, shift=None, leave_type=None, ignore_validate=False):
 	if not frappe.db.exists('Attendance', {'employee':employee, 'attendance_date':attendance_date, 'docstatus':('!=', '2')}):
-		doc_dict = {
+		company = frappe.db.get_value('Employee', employee, 'company')
+		attendance = frappe.get_doc({
 			'doctype': 'Attendance',
 			'employee': employee,
 			'attendance_date': attendance_date,
 			'status': status,
-			'company': employee_doc.company,
-			'shift': shift
-		}
-		attendance = frappe.get_doc(doc_dict).insert()
+			'company': company,
+			'shift': shift,
+			'leave_type': leave_type
+		})
+		attendance.flags.ignore_validate = ignore_validate
+		attendance.insert()
 		attendance.submit()
 		return attendance.name
 
diff --git a/erpnext/hr/doctype/employee/employee_dashboard.py b/erpnext/hr/doctype/employee/employee_dashboard.py
index 11ad83b..0203332 100644
--- a/erpnext/hr/doctype/employee/employee_dashboard.py
+++ b/erpnext/hr/doctype/employee/employee_dashboard.py
@@ -6,6 +6,9 @@
 		'heatmap': True,
 		'heatmap_message': _('This is based on the attendance of this Employee'),
 		'fieldname': 'employee',
+		'non_standard_fieldnames': {
+			'Bank Account': 'party'
+		},
 		'transactions': [
 			{
 				'label': _('Leave and Attendance'),
@@ -33,7 +36,7 @@
 			},
 			{
 				'label': _('Payroll'),
-				'items': ['Salary Structure Assignment', 'Salary Slip', 'Additional Salary', 'Timesheet','Employee Incentive', 'Retention Bonus']
+				'items': ['Salary Structure Assignment', 'Salary Slip', 'Additional Salary', 'Timesheet','Employee Incentive', 'Retention Bonus', 'Bank Account']
 			},
 			{
 				'label': _('Training'),
diff --git a/erpnext/hr/doctype/employee_advance/employee_advance.py b/erpnext/hr/doctype/employee_advance/employee_advance.py
index f10e3b6..f0663ae 100644
--- a/erpnext/hr/doctype/employee_advance/employee_advance.py
+++ b/erpnext/hr/doctype/employee_advance/employee_advance.py
@@ -136,9 +136,18 @@
 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
+
 	je = frappe.new_doc('Journal Entry')
 	je.posting_date = nowdate()
-	je.voucher_type = 'Bank Entry'
+	# 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.company = company
 	je.remark = 'Return against Employee Advance: ' + employee_advance_name
 
diff --git a/erpnext/accounts/doctype/account_subtype/__init__.py b/erpnext/hr/doctype/employee_other_income/__init__.py
similarity index 100%
copy from erpnext/accounts/doctype/account_subtype/__init__.py
copy to erpnext/hr/doctype/employee_other_income/__init__.py
diff --git a/erpnext/hr/doctype/employee_other_income/employee_other_income.js b/erpnext/hr/doctype/employee_other_income/employee_other_income.js
new file mode 100644
index 0000000..c1a74e8
--- /dev/null
+++ b/erpnext/hr/doctype/employee_other_income/employee_other_income.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('Employee Other Income', {
+	// refresh: function(frm) {
+
+	// }
+});
diff --git a/erpnext/hr/doctype/employee_other_income/employee_other_income.json b/erpnext/hr/doctype/employee_other_income/employee_other_income.json
new file mode 100644
index 0000000..2dd6c10
--- /dev/null
+++ b/erpnext/hr/doctype/employee_other_income/employee_other_income.json
@@ -0,0 +1,138 @@
+{
+ "actions": [],
+ "autoname": "HR-INCOME-.######",
+ "creation": "2020-03-18 15:04:40.767434",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "employee",
+  "employee_name",
+  "payroll_period",
+  "column_break_3",
+  "company",
+  "source",
+  "amount",
+  "amended_from"
+ ],
+ "fields": [
+  {
+   "fieldname": "employee",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "label": "Employee",
+   "options": "Employee",
+   "reqd": 1
+  },
+  {
+   "fieldname": "payroll_period",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "label": "Payroll Period",
+   "options": "Payroll Period",
+   "reqd": 1
+  },
+  {
+   "fieldname": "column_break_3",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "company",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "label": "Company",
+   "options": "Company",
+   "reqd": 1
+  },
+  {
+   "fieldname": "source",
+   "fieldtype": "Data",
+   "label": "Source"
+  },
+  {
+   "fieldname": "amount",
+   "fieldtype": "Currency",
+   "in_list_view": 1,
+   "label": "Amount",
+   "options": "Company:company:default_currency",
+   "reqd": 1
+  },
+  {
+   "fetch_from": "employee.employee_name",
+   "fieldname": "employee_name",
+   "fieldtype": "Data",
+   "label": "Employee Name",
+   "read_only": 1
+  },
+  {
+   "fieldname": "amended_from",
+   "fieldtype": "Link",
+   "label": "Amended From",
+   "no_copy": 1,
+   "options": "Employee Other Income",
+   "print_hide": 1,
+   "read_only": 1
+  }
+ ],
+ "is_submittable": 1,
+ "links": [],
+ "modified": "2020-03-19 18:06:45.361830",
+ "modified_by": "Administrator",
+ "module": "HR",
+ "name": "Employee Other Income",
+ "owner": "Administrator",
+ "permissions": [
+  {
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "export": 1,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "System Manager",
+   "share": 1,
+   "write": 1
+  },
+  {
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "export": 1,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "HR Manager",
+   "share": 1,
+   "write": 1
+  },
+  {
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "export": 1,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "HR User",
+   "share": 1,
+   "write": 1
+  },
+  {
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "export": 1,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "Employee",
+   "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/hr/doctype/employee_other_income/employee_other_income.py b/erpnext/hr/doctype/employee_other_income/employee_other_income.py
new file mode 100644
index 0000000..ab63c0d
--- /dev/null
+++ b/erpnext/hr/doctype/employee_other_income/employee_other_income.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 EmployeeOtherIncome(Document):
+	pass
diff --git a/erpnext/hr/doctype/employee_other_income/test_employee_other_income.py b/erpnext/hr/doctype/employee_other_income/test_employee_other_income.py
new file mode 100644
index 0000000..2eeca7a
--- /dev/null
+++ b/erpnext/hr/doctype/employee_other_income/test_employee_other_income.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 TestEmployeeOtherIncome(unittest.TestCase):
+	pass
diff --git a/erpnext/hr/doctype/employee_tax_exemption_declaration/employee_tax_exemption_declaration.json b/erpnext/hr/doctype/employee_tax_exemption_declaration/employee_tax_exemption_declaration.json
index e102ff8..18fad85 100644
--- a/erpnext/hr/doctype/employee_tax_exemption_declaration/employee_tax_exemption_declaration.json
+++ b/erpnext/hr/doctype/employee_tax_exemption_declaration/employee_tax_exemption_declaration.json
@@ -1,620 +1,180 @@
 {
- "allow_copy": 0, 
- "allow_events_in_timeline": 0, 
- "allow_guest_to_view": 0, 
- "allow_import": 1, 
- "allow_rename": 1, 
- "autoname": "HR-TAX-DEC-.YYYY.-.#####", 
- "beta": 0, 
- "creation": "2018-04-13 16:53:36.175504", 
- "custom": 0, 
- "docstatus": 0, 
- "doctype": "DocType", 
- "document_type": "", 
- "editable_grid": 1, 
- "engine": "InnoDB", 
+ "actions": [],
+ "allow_import": 1,
+ "allow_rename": 1,
+ "autoname": "HR-TAX-DEC-.YYYY.-.#####",
+ "creation": "2018-04-13 16:53:36.175504",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "employee",
+  "employee_name",
+  "department",
+  "column_break_2",
+  "payroll_period",
+  "company",
+  "amended_from",
+  "section_break_8",
+  "declarations",
+  "section_break_10",
+  "total_declared_amount",
+  "column_break_12",
+  "total_exemption_amount"
+ ],
  "fields": [
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fetch_if_empty": 0, 
-   "fieldname": "employee", 
-   "fieldtype": "Link", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Employee", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Employee", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 1, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "employee",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "label": "Employee",
+   "options": "Employee",
+   "reqd": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fetch_from": "employee.employee_name", 
-   "fetch_if_empty": 0, 
-   "fieldname": "employee_name", 
-   "fieldtype": "Data", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Employee Name", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 1, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "fetch_from": "employee.employee_name",
+   "fieldname": "employee_name",
+   "fieldtype": "Data",
+   "label": "Employee Name",
+   "read_only": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fetch_from": "employee.department", 
-   "fetch_if_empty": 0, 
-   "fieldname": "department", 
-   "fieldtype": "Link", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Department", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Department", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 1, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "fetch_from": "employee.department",
+   "fieldname": "department",
+   "fieldtype": "Link",
+   "label": "Department",
+   "options": "Department",
+   "read_only": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fetch_if_empty": 0, 
-   "fieldname": "column_break_2", 
-   "fieldtype": "Column Break", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "column_break_2",
+   "fieldtype": "Column Break"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fetch_if_empty": 0, 
-   "fieldname": "payroll_period", 
-   "fieldtype": "Link", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Payroll Period", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Payroll Period", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 1, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "payroll_period",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "label": "Payroll Period",
+   "options": "Payroll Period",
+   "reqd": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fetch_from": "employee.company", 
-   "fetch_if_empty": 0, 
-   "fieldname": "company", 
-   "fieldtype": "Link", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Company", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Company", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "fetch_from": "employee.company",
+   "fieldname": "company",
+   "fieldtype": "Link",
+   "label": "Company",
+   "options": "Company"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fetch_if_empty": 0, 
-   "fieldname": "amended_from", 
-   "fieldtype": "Link", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Amended From", 
-   "length": 0, 
-   "no_copy": 1, 
-   "options": "Employee Tax Exemption Declaration", 
-   "permlevel": 0, 
-   "print_hide": 1, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 1, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "amended_from",
+   "fieldtype": "Link",
+   "label": "Amended From",
+   "no_copy": 1,
+   "options": "Employee Tax Exemption Declaration",
+   "print_hide": 1,
+   "read_only": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fetch_if_empty": 0, 
-   "fieldname": "section_break_8", 
-   "fieldtype": "Section Break", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "section_break_8",
+   "fieldtype": "Section Break"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fetch_if_empty": 0, 
-   "fieldname": "declarations", 
-   "fieldtype": "Table", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Declarations", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Employee Tax Exemption Declaration Category", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "declarations",
+   "fieldtype": "Table",
+   "label": "Declarations",
+   "options": "Employee Tax Exemption Declaration Category"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fetch_if_empty": 0, 
-   "fieldname": "section_break_10", 
-   "fieldtype": "Section Break", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "section_break_10",
+   "fieldtype": "Section Break"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fetch_if_empty": 0, 
-   "fieldname": "total_declared_amount", 
-   "fieldtype": "Currency", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Total Declared Amount", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 1, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "total_declared_amount",
+   "fieldtype": "Currency",
+   "label": "Total Declared Amount",
+   "read_only": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fetch_if_empty": 0, 
-   "fieldname": "column_break_12", 
-   "fieldtype": "Column Break", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "column_break_12",
+   "fieldtype": "Column Break"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fetch_if_empty": 0, 
-   "fieldname": "total_exemption_amount", 
-   "fieldtype": "Currency", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Total Exemption Amount", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 1, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fetch_if_empty": 0, 
-   "fieldname": "other_incomes_section", 
-   "fieldtype": "Section Break", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Other Incomes", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fetch_if_empty": 0, 
-   "fieldname": "income_from_other_sources", 
-   "fieldtype": "Currency", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Income From Other Sources", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
+   "fieldname": "total_exemption_amount",
+   "fieldtype": "Currency",
+   "label": "Total Exemption Amount",
+   "read_only": 1
   }
- ], 
- "has_web_view": 0, 
- "hide_heading": 0, 
- "hide_toolbar": 0, 
- "idx": 0, 
- "image_view": 0, 
- "in_create": 0, 
- "is_submittable": 1, 
- "issingle": 0, 
- "istable": 0, 
- "max_attachments": 0, 
- "modified": "2019-05-11 16:13:50.472670", 
- "modified_by": "Administrator", 
- "module": "HR", 
- "name": "Employee Tax Exemption Declaration", 
- "name_case": "", 
- "owner": "Administrator", 
+ ],
+ "is_submittable": 1,
+ "links": [],
+ "modified": "2020-03-18 14:56:25.625717",
+ "modified_by": "Administrator",
+ "module": "HR",
+ "name": "Employee Tax Exemption Declaration",
+ "owner": "Administrator",
  "permissions": [
   {
-   "amend": 1, 
-   "cancel": 1, 
-   "create": 1, 
-   "delete": 1, 
-   "email": 1, 
-   "export": 1, 
-   "if_owner": 0, 
-   "import": 0, 
-   "permlevel": 0, 
-   "print": 1, 
-   "read": 1, 
-   "report": 1, 
-   "role": "System Manager", 
-   "set_user_permissions": 0, 
-   "share": 1, 
-   "submit": 1, 
+   "amend": 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
-  }, 
+  },
   {
-   "amend": 1, 
-   "cancel": 1, 
-   "create": 1, 
-   "delete": 1, 
-   "email": 1, 
-   "export": 1, 
-   "if_owner": 0, 
-   "import": 0, 
-   "permlevel": 0, 
-   "print": 1, 
-   "read": 1, 
-   "report": 1, 
-   "role": "HR Manager", 
-   "set_user_permissions": 0, 
-   "share": 1, 
-   "submit": 1, 
+   "amend": 1,
+   "cancel": 1,
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "export": 1,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "HR Manager",
+   "share": 1,
+   "submit": 1,
    "write": 1
-  }, 
+  },
   {
-   "amend": 1, 
-   "cancel": 1, 
-   "create": 1, 
-   "delete": 1, 
-   "email": 1, 
-   "export": 1, 
-   "if_owner": 0, 
-   "import": 0, 
-   "permlevel": 0, 
-   "print": 1, 
-   "read": 1, 
-   "report": 1, 
-   "role": "HR User", 
-   "set_user_permissions": 0, 
-   "share": 1, 
-   "submit": 1, 
+   "amend": 1,
+   "cancel": 1,
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "export": 1,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "HR User",
+   "share": 1,
+   "submit": 1,
    "write": 1
-  }, 
+  },
   {
-   "amend": 1, 
-   "cancel": 1, 
-   "create": 1, 
-   "delete": 1, 
-   "email": 1, 
-   "export": 1, 
-   "if_owner": 0, 
-   "import": 0, 
-   "permlevel": 0, 
-   "print": 1, 
-   "read": 1, 
-   "report": 1, 
-   "role": "Employee", 
-   "set_user_permissions": 0, 
-   "share": 1, 
-   "submit": 1, 
+   "amend": 1,
+   "cancel": 1,
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "export": 1,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "Employee",
+   "share": 1,
+   "submit": 1,
    "write": 1
   }
- ], 
- "quick_entry": 0, 
- "read_only": 0, 
- "read_only_onload": 0, 
- "show_name_in_global_search": 0, 
- "sort_field": "modified", 
- "sort_order": "DESC", 
- "track_changes": 1, 
- "track_seen": 0, 
- "track_views": 0
+ ],
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
 }
\ No newline at end of file
diff --git a/erpnext/hr/doctype/employee_tax_exemption_declaration/employee_tax_exemption_declaration.py b/erpnext/hr/doctype/employee_tax_exemption_declaration/employee_tax_exemption_declaration.py
index f2bba7a..fb71a28 100644
--- a/erpnext/hr/doctype/employee_tax_exemption_declaration/employee_tax_exemption_declaration.py
+++ b/erpnext/hr/doctype/employee_tax_exemption_declaration/employee_tax_exemption_declaration.py
@@ -8,31 +8,17 @@
 from frappe import _
 from frappe.utils import flt
 from frappe.model.mapper import get_mapped_doc
-from erpnext.hr.utils import validate_tax_declaration, get_total_exemption_amount, calculate_annual_eligible_hra_exemption
-
-class DuplicateDeclarationError(frappe.ValidationError): pass
+from erpnext.hr.utils import validate_tax_declaration, get_total_exemption_amount, \
+	calculate_annual_eligible_hra_exemption, validate_duplicate_exemption_for_payroll_period
 
 class EmployeeTaxExemptionDeclaration(Document):
 	def validate(self):
 		validate_tax_declaration(self.declarations)
-		self.validate_duplicate()
+		validate_duplicate_exemption_for_payroll_period(self.doctype, self.name, self.payroll_period, self.employee)
 		self.set_total_declared_amount()
 		self.set_total_exemption_amount()
 		self.calculate_hra_exemption()
 
-	def validate_duplicate(self):
-		duplicate = frappe.db.get_value("Employee Tax Exemption Declaration",
-			filters = {
-				"employee": self.employee,
-				"payroll_period": self.payroll_period,
-				"name": ["!=", self.name],
-				"docstatus": ["!=", 2]
-			}
-		)
-		if duplicate:
-			frappe.throw(_("Duplicate Tax Declaration of {0} for period {1}")
-				.format(self.employee, self.payroll_period), DuplicateDeclarationError)
-
 	def set_total_declared_amount(self):
 		self.total_declared_amount = 0.0
 		for d in self.declarations:
diff --git a/erpnext/hr/doctype/employee_tax_exemption_declaration/test_employee_tax_exemption_declaration.py b/erpnext/hr/doctype/employee_tax_exemption_declaration/test_employee_tax_exemption_declaration.py
index 9c87bbd..9549fd1 100644
--- a/erpnext/hr/doctype/employee_tax_exemption_declaration/test_employee_tax_exemption_declaration.py
+++ b/erpnext/hr/doctype/employee_tax_exemption_declaration/test_employee_tax_exemption_declaration.py
@@ -6,7 +6,7 @@
 import frappe, erpnext
 import unittest
 from erpnext.hr.doctype.employee.test_employee import make_employee
-from erpnext.hr.doctype.employee_tax_exemption_declaration.employee_tax_exemption_declaration import DuplicateDeclarationError
+from erpnext.hr.utils import DuplicateDeclarationError
 
 class TestEmployeeTaxExemptionDeclaration(unittest.TestCase):
 	def setUp(self):
diff --git a/erpnext/hr/doctype/employee_tax_exemption_proof_submission/employee_tax_exemption_proof_submission.json b/erpnext/hr/doctype/employee_tax_exemption_proof_submission/employee_tax_exemption_proof_submission.json
index c170c16..8b117a2 100644
--- a/erpnext/hr/doctype/employee_tax_exemption_proof_submission/employee_tax_exemption_proof_submission.json
+++ b/erpnext/hr/doctype/employee_tax_exemption_proof_submission/employee_tax_exemption_proof_submission.json
@@ -21,8 +21,6 @@
   "total_actual_amount",
   "column_break_12",
   "exemption_amount",
-  "other_incomes_section",
-  "income_from_other_sources",
   "attachment_section",
   "attachments",
   "amended_from"
@@ -112,16 +110,6 @@
    "read_only": 1
   },
   {
-   "fieldname": "other_incomes_section",
-   "fieldtype": "Section Break",
-   "label": "Other Incomes"
-  },
-  {
-   "fieldname": "income_from_other_sources",
-   "fieldtype": "Currency",
-   "label": "Income From Other Sources"
-  },
-  {
    "fieldname": "attachment_section",
    "fieldtype": "Section Break"
   },
@@ -142,7 +130,7 @@
  ],
  "is_submittable": 1,
  "links": [],
- "modified": "2020-03-02 19:02:15.398486",
+ "modified": "2020-03-18 14:55:51.420016",
  "modified_by": "Administrator",
  "module": "HR",
  "name": "Employee Tax Exemption Proof Submission",
diff --git a/erpnext/hr/doctype/employee_tax_exemption_proof_submission/employee_tax_exemption_proof_submission.py b/erpnext/hr/doctype/employee_tax_exemption_proof_submission/employee_tax_exemption_proof_submission.py
index 97ceb63..5bc33a6 100644
--- a/erpnext/hr/doctype/employee_tax_exemption_proof_submission/employee_tax_exemption_proof_submission.py
+++ b/erpnext/hr/doctype/employee_tax_exemption_proof_submission/employee_tax_exemption_proof_submission.py
@@ -7,7 +7,8 @@
 from frappe.model.document import Document
 from frappe import _
 from frappe.utils import flt
-from erpnext.hr.utils import validate_tax_declaration, get_total_exemption_amount, calculate_hra_exemption_for_period
+from erpnext.hr.utils import validate_tax_declaration, get_total_exemption_amount, \
+	calculate_hra_exemption_for_period, validate_duplicate_exemption_for_payroll_period
 
 class EmployeeTaxExemptionProofSubmission(Document):
 	def validate(self):
@@ -15,6 +16,7 @@
 		self.set_total_actual_amount()
 		self.set_total_exemption_amount()
 		self.calculate_hra_exemption()
+		validate_duplicate_exemption_for_payroll_period(self.doctype, self.name, self.payroll_period, self.employee)
 
 	def set_total_actual_amount(self):
 		self.total_actual_amount = flt(self.get("house_rent_payment_amount"))
@@ -32,4 +34,4 @@
 				self.exemption_amount += hra_exemption["total_eligible_hra_exemption"]
 				self.monthly_hra_exemption = hra_exemption["monthly_exemption"]
 				self.monthly_house_rent = hra_exemption["monthly_house_rent"]
-				self.total_eligible_hra_exemption = hra_exemption["total_eligible_hra_exemption"]
\ No newline at end of file
+				self.total_eligible_hra_exemption = hra_exemption["total_eligible_hra_exemption"]
diff --git a/erpnext/hr/doctype/expense_claim/expense_claim.js b/erpnext/hr/doctype/expense_claim/expense_claim.js
index 88f3865..fb23103 100644
--- a/erpnext/hr/doctype/expense_claim/expense_claim.js
+++ b/erpnext/hr/doctype/expense_claim/expense_claim.js
@@ -17,7 +17,7 @@
 			return;
 		}
 		return frappe.call({
-			method: "erpnext.hr.doctype.expense_claim.expense_claim.get_expense_claim_account",
+			method: "erpnext.hr.doctype.expense_claim.expense_claim.get_expense_claim_account_and_cost_center",
 			args: {
 				"expense_claim_type": d.expense_type,
 				"company": doc.company
@@ -25,6 +25,7 @@
 			callback: function(r) {
 				if (r.message) {
 					d.default_account = r.message.account;
+					d.cost_center = r.message.cost_center;
 				}
 			}
 		});
diff --git a/erpnext/hr/doctype/expense_claim/expense_claim.py b/erpnext/hr/doctype/expense_claim/expense_claim.py
index fe8afdf..ac1bfa1 100644
--- a/erpnext/hr/doctype/expense_claim/expense_claim.py
+++ b/erpnext/hr/doctype/expense_claim/expense_claim.py
@@ -2,9 +2,9 @@
 # License: GNU General Public License v3. See license.txt
 
 from __future__ import unicode_literals
-import frappe
+import frappe, erpnext
 from frappe import _
-from frappe.utils import get_fullname, flt, cstr
+from frappe.utils import get_fullname, flt, cstr, get_link_to_form
 from frappe.model.document import Document
 from erpnext.hr.utils import set_employee_name
 from erpnext.accounts.party import get_party_account
@@ -76,6 +76,7 @@
 
 	def on_cancel(self):
 		self.update_task_and_project()
+		self.ignore_linked_doctypes = ('GL Entry', 'Stock Ledger Entry')
 		if self.payable_account:
 			self.make_gl_entries(cancel=True)
 
@@ -192,7 +193,8 @@
 	def validate_account_details(self):
 		for data in self.expenses:
 			if not data.cost_center:
-				frappe.throw(_("Cost center is required to book an expense claim"))
+				frappe.throw(_("Row {0}: {1} is required in the expenses table to book an expense claim.")
+					.format(data.idx, frappe.bold("Cost Center")))
 
 		if self.is_paid:
 			if not self.mode_of_payment:
@@ -259,10 +261,17 @@
 			if not expense.default_account or not validate:
 				expense.default_account = get_expense_claim_account(expense.expense_type, self.company)["account"]
 
-def update_reimbursed_amount(doc):
-	amt = frappe.db.sql("""select ifnull(sum(debit_in_account_currency), 0) as amt
+def update_reimbursed_amount(doc, jv=None):
+
+	condition = ""
+
+	if jv:
+		condition += "and voucher_no = '{0}'".format(jv)
+
+	amt = frappe.db.sql("""select ifnull(sum(debit_in_account_currency), 0) - ifnull(sum(credit_in_account_currency), 0)as amt
 		from `tabGL Entry` where against_voucher_type = 'Expense Claim' and against_voucher = %s
-		and party = %s """, (doc.name, doc.employee) ,as_dict=1)[0].amt
+		and party = %s {condition}""".format(condition=condition), #nosec
+		(doc.name, doc.employee) ,as_dict=1)[0].amt
 
 	doc.total_amount_reimbursed = amt
 	frappe.db.set_value("Expense Claim", doc.name , "total_amount_reimbursed", amt)
@@ -309,12 +318,22 @@
 	return je.as_dict()
 
 @frappe.whitelist()
+def get_expense_claim_account_and_cost_center(expense_claim_type, company):
+	data = get_expense_claim_account(expense_claim_type, company)
+	cost_center = erpnext.get_default_cost_center(company)
+
+	return {
+		"account": data.get("account"),
+		"cost_center": cost_center
+	}
+
+@frappe.whitelist()
 def get_expense_claim_account(expense_claim_type, company):
 	account = frappe.db.get_value("Expense Claim Account",
 		{"parent": expense_claim_type, "company": company}, "default_account")
 	if not account:
-		frappe.throw(_("Please set default account in Expense Claim Type {0}")
-			.format(expense_claim_type))
+		frappe.throw(_("Set the default account for the {0} {1}")
+			.format(frappe.bold("Expense Claim Type"), get_link_to_form("Expense Claim Type", expense_claim_type)))
 
 	return {
 		"account": account
diff --git a/erpnext/hr/doctype/hr_settings/hr_settings.json b/erpnext/hr/doctype/hr_settings/hr_settings.json
index 90f4988..9161ed8 100644
--- a/erpnext/hr/doctype/hr_settings/hr_settings.json
+++ b/erpnext/hr/doctype/hr_settings/hr_settings.json
@@ -13,10 +13,12 @@
   "stop_birthday_reminders",
   "expense_approver_mandatory_in_expense_claim",
   "payroll_settings",
+  "payroll_based_on", 
+  "max_working_hours_against_timesheet", 
   "include_holidays_in_total_working_days",
   "disable_rounded_total",
-  "max_working_hours_against_timesheet",
   "column_break_11",
+  "daily_wages_fraction_for_half_day", 
   "email_salary_slip_to_employee",
   "encrypt_salary_slips_in_emails",
   "password_policy",
@@ -184,13 +186,27 @@
    "fieldtype": "Link",
    "label": "Role Allowed to Create Backdated Leave Application",
    "options": "Role"
+  },
+  {
+   "default": "Leave",
+   "fieldname": "payroll_based_on",
+   "fieldtype": "Select",
+   "label": "Calculate Working Days in Payroll based on",
+   "options": "Leave\nAttendance"
+  },
+  {
+   "default": "0.5",
+   "description": "The fraction of daily wages to be paid for half-day attendance",
+   "fieldname": "daily_wages_fraction_for_half_day",
+   "fieldtype": "Float",
+   "label": "Daily Wages Fraction for Half Day"
   }
  ],
  "icon": "fa fa-cog",
  "idx": 1,
  "issingle": 1,
  "links": [],
- "modified": "2020-01-06 18:46:30.189815",
+ "modified": "2020-04-13 21:20:59.382394",
  "modified_by": "Administrator",
  "module": "HR",
  "name": "HR Settings",
diff --git a/erpnext/hr/doctype/hr_settings/hr_settings.py b/erpnext/hr/doctype/hr_settings/hr_settings.py
index bf91906..5ed4c87 100644
--- a/erpnext/hr/doctype/hr_settings/hr_settings.py
+++ b/erpnext/hr/doctype/hr_settings/hr_settings.py
@@ -15,6 +15,9 @@
 		self.set_naming_series()
 		self.validate_password_policy()
 
+		if not self.daily_wages_fraction_for_half_day:
+			self.daily_wages_fraction_for_half_day = 0.5
+
 	def set_naming_series(self):
 		from erpnext.setup.doctype.naming_series.naming_series import set_by_naming_series
 		set_by_naming_series("Employee", "employee_number",
diff --git a/erpnext/education/doctype/video/__init__.py b/erpnext/hr/doctype/income_tax_slab/__init__.py
similarity index 100%
copy from erpnext/education/doctype/video/__init__.py
copy to erpnext/hr/doctype/income_tax_slab/__init__.py
diff --git a/erpnext/hr/doctype/income_tax_slab/income_tax_slab.js b/erpnext/hr/doctype/income_tax_slab/income_tax_slab.js
new file mode 100644
index 0000000..73a54eb
--- /dev/null
+++ b/erpnext/hr/doctype/income_tax_slab/income_tax_slab.js
@@ -0,0 +1,6 @@
+// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+frappe.ui.form.on('Income Tax Slab', {
+
+});
diff --git a/erpnext/hr/doctype/income_tax_slab/income_tax_slab.json b/erpnext/hr/doctype/income_tax_slab/income_tax_slab.json
new file mode 100644
index 0000000..f74315f
--- /dev/null
+++ b/erpnext/hr/doctype/income_tax_slab/income_tax_slab.json
@@ -0,0 +1,152 @@
+{
+ "actions": [],
+ "autoname": "Prompt",
+ "creation": "2020-03-17 16:50:35.564915",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "effective_from",
+  "company",
+  "column_break_3",
+  "allow_tax_exemption",
+  "standard_tax_exemption_amount",
+  "disabled",
+  "amended_from",
+  "taxable_salary_slabs_section",
+  "slabs",
+  "taxes_and_charges_on_income_tax_section",
+  "other_taxes_and_charges"
+ ],
+ "fields": [
+  {
+   "fieldname": "effective_from",
+   "fieldtype": "Date",
+   "in_list_view": 1,
+   "label": "Effective from",
+   "reqd": 1
+  },
+  {
+   "fieldname": "column_break_3",
+   "fieldtype": "Column Break"
+  },
+  {
+   "default": "0",
+   "description": "If enabled, Tax Exemption Declaration will be considered for income tax calculation.",
+   "fieldname": "allow_tax_exemption",
+   "fieldtype": "Check",
+   "label": "Allow Tax Exemption"
+  },
+  {
+   "fieldname": "taxable_salary_slabs_section",
+   "fieldtype": "Section Break",
+   "label": "Taxable Salary Slabs"
+  },
+  {
+   "fieldname": "amended_from",
+   "fieldtype": "Link",
+   "label": "Amended From",
+   "no_copy": 1,
+   "options": "Income Tax Slab",
+   "print_hide": 1,
+   "read_only": 1
+  },
+  {
+   "fieldname": "slabs",
+   "fieldtype": "Table",
+   "label": "Taxable Salary Slabs",
+   "options": "Taxable Salary Slab",
+   "reqd": 1
+  },
+  {
+   "allow_on_submit": 1,
+   "default": "0",
+   "fieldname": "disabled",
+   "fieldtype": "Check",
+   "label": "Disabled"
+  },
+  {
+   "depends_on": "allow_tax_exemption",
+   "fieldname": "standard_tax_exemption_amount",
+   "fieldtype": "Currency",
+   "label": "Standard Tax Exemption Amount",
+   "options": "Company:company:default_currency"
+  },
+  {
+   "fieldname": "company",
+   "fieldtype": "Link",
+   "label": "Company",
+   "options": "Company"
+  },
+  {
+   "collapsible": 1,
+   "collapsible_depends_on": "other_taxes_and_charges",
+   "fieldname": "taxes_and_charges_on_income_tax_section",
+   "fieldtype": "Section Break",
+   "label": "Taxes and Charges on Income Tax"
+  },
+  {
+   "fieldname": "other_taxes_and_charges",
+   "fieldtype": "Table",
+   "label": "Other Taxes and Charges",
+   "options": "Income Tax Slab Other Charges"
+  }
+ ],
+ "is_submittable": 1,
+ "links": [],
+ "modified": "2020-04-29 15:08:21.436120",
+ "modified_by": "Administrator",
+ "module": "HR",
+ "name": "Income Tax Slab",
+ "owner": "Administrator",
+ "permissions": [
+  {
+   "amend": 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
+  },
+  {
+   "amend": 1,
+   "cancel": 1,
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "export": 1,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "HR Manager",
+   "share": 1,
+   "submit": 1,
+   "write": 1
+  },
+  {
+   "amend": 1,
+   "cancel": 1,
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "export": 1,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "HR User",
+   "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/accounts/doctype/account_subtype/account_subtype.py b/erpnext/hr/doctype/income_tax_slab/income_tax_slab.py
similarity index 60%
copy from erpnext/accounts/doctype/account_subtype/account_subtype.py
copy to erpnext/hr/doctype/income_tax_slab/income_tax_slab.py
index 46c45cc..253f023 100644
--- a/erpnext/accounts/doctype/account_subtype/account_subtype.py
+++ b/erpnext/hr/doctype/income_tax_slab/income_tax_slab.py
@@ -1,9 +1,10 @@
 # -*- coding: utf-8 -*-
-# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
+# 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 AccountSubtype(Document):
+class IncomeTaxSlab(Document):
 	pass
diff --git a/erpnext/hr/doctype/income_tax_slab/test_income_tax_slab.py b/erpnext/hr/doctype/income_tax_slab/test_income_tax_slab.py
new file mode 100644
index 0000000..deaaf65
--- /dev/null
+++ b/erpnext/hr/doctype/income_tax_slab/test_income_tax_slab.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 TestIncomeTaxSlab(unittest.TestCase):
+	pass
diff --git a/erpnext/accounts/doctype/account_subtype/__init__.py b/erpnext/hr/doctype/income_tax_slab_other_charges/__init__.py
similarity index 100%
copy from erpnext/accounts/doctype/account_subtype/__init__.py
copy to erpnext/hr/doctype/income_tax_slab_other_charges/__init__.py
diff --git a/erpnext/hr/doctype/income_tax_slab_other_charges/income_tax_slab_other_charges.json b/erpnext/hr/doctype/income_tax_slab_other_charges/income_tax_slab_other_charges.json
new file mode 100644
index 0000000..b23fb3d
--- /dev/null
+++ b/erpnext/hr/doctype/income_tax_slab_other_charges/income_tax_slab_other_charges.json
@@ -0,0 +1,75 @@
+{
+ "actions": [],
+ "creation": "2020-04-24 11:46:59.041180",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "description",
+  "column_break_2",
+  "percent",
+  "conditions_section",
+  "min_taxable_income",
+  "column_break_7",
+  "max_taxable_income"
+ ],
+ "fields": [
+  {
+   "fieldname": "column_break_2",
+   "fieldtype": "Column Break"
+  },
+  {
+   "columns": 2,
+   "fieldname": "min_taxable_income",
+   "fieldtype": "Currency",
+   "in_list_view": 1,
+   "label": "Min Taxable Income",
+   "options": "Company:company:default_currency"
+  },
+  {
+   "columns": 4,
+   "fieldname": "description",
+   "fieldtype": "Data",
+   "in_list_view": 1,
+   "label": "Description",
+   "reqd": 1
+  },
+  {
+   "columns": 2,
+   "fieldname": "percent",
+   "fieldtype": "Percent",
+   "in_list_view": 1,
+   "label": "Percent",
+   "reqd": 1
+  },
+  {
+   "fieldname": "conditions_section",
+   "fieldtype": "Section Break",
+   "label": "Conditions"
+  },
+  {
+   "fieldname": "column_break_7",
+   "fieldtype": "Column Break"
+  },
+  {
+   "columns": 2,
+   "fieldname": "max_taxable_income",
+   "fieldtype": "Currency",
+   "in_list_view": 1,
+   "label": "Max Taxable Income",
+   "options": "Company:company:default_currency"
+  }
+ ],
+ "istable": 1,
+ "links": [],
+ "modified": "2020-04-24 13:27:43.598967",
+ "modified_by": "Administrator",
+ "module": "HR",
+ "name": "Income Tax Slab Other Charges",
+ "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/hr/doctype/income_tax_slab_other_charges/income_tax_slab_other_charges.py b/erpnext/hr/doctype/income_tax_slab_other_charges/income_tax_slab_other_charges.py
new file mode 100644
index 0000000..b4098ec
--- /dev/null
+++ b/erpnext/hr/doctype/income_tax_slab_other_charges/income_tax_slab_other_charges.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 IncomeTaxSlabOtherCharges(Document):
+	pass
diff --git a/erpnext/hr/doctype/leave_allocation/leave_allocation.py b/erpnext/hr/doctype/leave_allocation/leave_allocation.py
index d13bb45..03fe3fa 100755
--- a/erpnext/hr/doctype/leave_allocation/leave_allocation.py
+++ b/erpnext/hr/doctype/leave_allocation/leave_allocation.py
@@ -30,16 +30,16 @@
 	def validate_leave_allocation_days(self):
 		company = frappe.db.get_value("Employee", self.employee, "company")
 		leave_period = get_leave_period(self.from_date, self.to_date, company)
-		max_leaves_allowed = frappe.db.get_value("Leave Type", self.leave_type, "max_leaves_allowed")
+		max_leaves_allowed = flt(frappe.db.get_value("Leave Type", self.leave_type, "max_leaves_allowed"))
 		if max_leaves_allowed > 0:
 			leave_allocated = 0
 			if leave_period:
 				leave_allocated = get_leave_allocation_for_period(self.employee, self.leave_type,
 					leave_period[0].from_date, leave_period[0].to_date)
-			leave_allocated += self.new_leaves_allocated
+			leave_allocated += flt(self.new_leaves_allocated)
 			if leave_allocated > max_leaves_allowed:
 				frappe.throw(_("Total allocated leaves are more days than maximum allocation of {0} leave type for employee {1} in the period")
-				.format(self.leave_type, self.employee))
+					.format(self.leave_type, self.employee))
 
 	def on_submit(self):
 		self.create_leave_ledger_entry()
diff --git a/erpnext/hr/doctype/leave_application/leave_application.json b/erpnext/hr/doctype/leave_application/leave_application.json
index cdb1add..74707a2 100644
--- a/erpnext/hr/doctype/leave_application/leave_application.json
+++ b/erpnext/hr/doctype/leave_application/leave_application.json
@@ -1,332 +1,337 @@
 {
-   "allow_import": 1,
-   "autoname": "naming_series:",
-   "creation": "2013-02-20 11:18:11",
-   "description": "Apply / Approve Leaves",
-   "doctype": "DocType",
-   "document_type": "Document",
-   "engine": "InnoDB",
-   "field_order": [
-    "naming_series",
-    "employee",
-    "employee_name",
-    "column_break_4",
-    "leave_type",
-    "department",
-    "leave_balance",
-    "section_break_5",
-    "from_date",
-    "to_date",
-    "half_day",
-    "half_day_date",
-    "total_leave_days",
-    "column_break1",
-    "description",
-    "section_break_7",
-    "leave_approver",
-    "leave_approver_name",
-    "column_break_18",
-    "status",
-    "salary_slip",
-    "sb10",
-    "posting_date",
-    "follow_via_email",
-    "color",
-    "column_break_17",
-    "company",
-    "letter_head",
-    "amended_from"
-   ],
-   "fields": [
-    {
-     "fieldname": "naming_series",
-     "fieldtype": "Select",
-     "label": "Series",
-     "no_copy": 1,
-     "options": "HR-LAP-.YYYY.-",
-     "print_hide": 1,
-     "reqd": 1,
-     "set_only_once": 1
-    },
-    {
-     "fieldname": "employee",
-     "fieldtype": "Link",
-     "in_global_search": 1,
-     "in_standard_filter": 1,
-     "label": "Employee",
-     "options": "Employee",
-     "reqd": 1,
-     "search_index": 1
-    },
-    {
-     "fieldname": "employee_name",
-     "fieldtype": "Data",
-     "in_global_search": 1,
-     "label": "Employee Name",
-     "read_only": 1
-    },
-    {
-     "fieldname": "column_break_4",
-     "fieldtype": "Column Break"
-    },
-    {
-     "fieldname": "leave_type",
-     "fieldtype": "Link",
-     "ignore_user_permissions": 1,
-     "in_standard_filter": 1,
-     "label": "Leave Type",
-     "options": "Leave Type",
-     "reqd": 1,
-     "search_index": 1
-    },
-    {
-     "fetch_from": "employee.department",
-     "fieldname": "department",
-     "fieldtype": "Link",
-     "label": "Department",
-     "options": "Department",
-     "read_only": 1
-    },
-    {
-     "fieldname": "leave_balance",
-     "fieldtype": "Float",
-     "label": "Leave Balance Before Application",
-     "no_copy": 1,
-     "read_only": 1
-    },
-    {
-     "fieldname": "section_break_5",
-     "fieldtype": "Section Break"
-    },
-    {
-     "fieldname": "from_date",
-     "fieldtype": "Date",
-     "in_list_view": 1,
-     "label": "From Date",
-     "reqd": 1,
-     "search_index": 1
-    },
-    {
-     "fieldname": "to_date",
-     "fieldtype": "Date",
-     "label": "To Date",
-     "reqd": 1,
-     "search_index": 1
-    },
-    {
-     "default": "0",
-     "fieldname": "half_day",
-     "fieldtype": "Check",
-     "label": "Half Day"
-    },
-    {
-     "depends_on": "eval:doc.half_day && (doc.from_date != doc.to_date)",
-     "fieldname": "half_day_date",
-     "fieldtype": "Date",
-     "label": "Half Day Date"
-    },
-    {
-     "fieldname": "total_leave_days",
-     "fieldtype": "Float",
-     "in_list_view": 1,
-     "label": "Total Leave Days",
-     "no_copy": 1,
-     "precision": "1",
-     "read_only": 1
-    },
-    {
-     "fieldname": "column_break1",
-     "fieldtype": "Column Break",
-     "print_width": "50%",
-     "width": "50%"
-    },
-    {
-     "fieldname": "description",
-     "fieldtype": "Small Text",
-     "label": "Reason"
-    },
-    {
-     "fieldname": "section_break_7",
-     "fieldtype": "Section Break"
-    },
-    {
-     "fieldname": "leave_approver",
-     "fieldtype": "Link",
-     "label": "Leave Approver",
-     "options": "User"
-    },
-    {
-     "fieldname": "leave_approver_name",
-     "fieldtype": "Data",
-     "label": "Leave Approver Name",
-     "read_only": 1
-    },
-    {
-     "fieldname": "column_break_18",
-     "fieldtype": "Column Break"
-    },
-    {
-     "default": "Open",
-     "fieldname": "status",
-     "fieldtype": "Select",
-     "in_standard_filter": 1,
-     "label": "Status",
-     "no_copy": 1,
-     "options": "Open\nApproved\nRejected\nCancelled"
-    },
-    {
-     "fieldname": "sb10",
-     "fieldtype": "Section Break"
-    },
-    {
-     "default": "Today",
-     "fieldname": "posting_date",
-     "fieldtype": "Date",
-     "label": "Posting Date",
-     "no_copy": 1,
-     "reqd": 1
-    },
-    {
-     "fieldname": "company",
-     "fieldtype": "Link",
-     "label": "Company",
-     "options": "Company",
-     "remember_last_selected_value": 1,
-     "reqd": 1
-    },
-    {
-     "allow_on_submit": 1,
-     "default": "1",
-     "fieldname": "follow_via_email",
-     "fieldtype": "Check",
-     "label": "Follow via Email",
-     "print_hide": 1
-    },
-    {
-     "fieldname": "column_break_17",
-     "fieldtype": "Column Break"
-    },
-    {
-     "fieldname": "salary_slip",
-     "fieldtype": "Link",
-     "label": "Salary Slip",
-     "options": "Salary Slip",
-     "print_hide": 1
-    },
-    {
-     "allow_on_submit": 1,
-     "fieldname": "letter_head",
-     "fieldtype": "Link",
-     "ignore_user_permissions": 1,
-     "label": "Letter Head",
-     "options": "Letter Head",
-     "print_hide": 1
-    },
-    {
-     "allow_on_submit": 1,
-     "fieldname": "color",
-     "fieldtype": "Color",
-     "label": "Color",
-     "print_hide": 1
-    },
-    {
-     "fieldname": "amended_from",
-     "fieldtype": "Link",
-     "ignore_user_permissions": 1,
-     "label": "Amended From",
-     "no_copy": 1,
-     "options": "Leave Application",
-     "print_hide": 1,
-     "read_only": 1
-    }
-   ],
-   "icon": "fa fa-calendar",
-   "idx": 1,
-   "is_submittable": 1,
-   "max_attachments": 3,
-   "modified": "2019-08-13 13:32:04.860848",
-   "modified_by": "Administrator",
-   "module": "HR",
-   "name": "Leave Application",
-   "owner": "Administrator",
-   "permissions": [
-    {
-     "create": 1,
-     "email": 1,
-     "print": 1,
-     "read": 1,
-     "report": 1,
-     "role": "Employee",
-     "share": 1,
-     "write": 1
-    },
-    {
-     "amend": 1,
-     "cancel": 1,
-     "create": 1,
-     "delete": 1,
-     "email": 1,
-     "export": 1,
-     "print": 1,
-     "read": 1,
-     "report": 1,
-     "role": "HR Manager",
-     "set_user_permissions": 1,
-     "share": 1,
-     "submit": 1,
-     "write": 1
-    },
-    {
-     "permlevel": 1,
-     "read": 1,
-     "role": "All"
-    },
-    {
-     "amend": 1,
-     "cancel": 1,
-     "create": 1,
-     "delete": 1,
-     "email": 1,
-     "print": 1,
-     "read": 1,
-     "report": 1,
-     "role": "HR User",
-     "set_user_permissions": 1,
-     "share": 1,
-     "submit": 1,
-     "write": 1
-    },
-    {
-     "amend": 1,
-     "cancel": 1,
-     "delete": 1,
-     "email": 1,
-     "print": 1,
-     "read": 1,
-     "report": 1,
-     "role": "Leave Approver",
-     "share": 1,
-     "submit": 1,
-     "write": 1
-    },
-    {
-     "permlevel": 1,
-     "read": 1,
-     "report": 1,
-     "role": "HR User",
-     "write": 1
-    },
-    {
-     "permlevel": 1,
-     "read": 1,
-     "report": 1,
-     "role": "Leave Approver",
-     "write": 1
-    }
-   ],
-   "search_fields": "employee,employee_name,leave_type,from_date,to_date,total_leave_days",
-   "sort_field": "modified",
-   "sort_order": "DESC",
-   "timeline_field": "employee",
-   "title_field": "employee_name"
-  }
\ No newline at end of file
+ "actions": [],
+ "allow_import": 1,
+ "autoname": "naming_series:",
+ "creation": "2013-02-20 11:18:11",
+ "description": "Apply / Approve Leaves",
+ "doctype": "DocType",
+ "document_type": "Document",
+ "engine": "InnoDB",
+ "field_order": [
+  "naming_series",
+  "employee",
+  "employee_name",
+  "column_break_4",
+  "leave_type",
+  "department",
+  "leave_balance",
+  "section_break_5",
+  "from_date",
+  "to_date",
+  "half_day",
+  "half_day_date",
+  "total_leave_days",
+  "column_break1",
+  "description",
+  "section_break_7",
+  "leave_approver",
+  "leave_approver_name",
+  "column_break_18",
+  "status",
+  "salary_slip",
+  "sb10",
+  "posting_date",
+  "follow_via_email",
+  "color",
+  "column_break_17",
+  "company",
+  "letter_head",
+  "amended_from"
+ ],
+ "fields": [
+  {
+   "fieldname": "naming_series",
+   "fieldtype": "Select",
+   "label": "Series",
+   "no_copy": 1,
+   "options": "HR-LAP-.YYYY.-",
+   "print_hide": 1,
+   "reqd": 1,
+   "set_only_once": 1
+  },
+  {
+   "fieldname": "employee",
+   "fieldtype": "Link",
+   "in_global_search": 1,
+   "in_standard_filter": 1,
+   "label": "Employee",
+   "options": "Employee",
+   "reqd": 1,
+   "search_index": 1
+  },
+  {
+   "fieldname": "employee_name",
+   "fieldtype": "Data",
+   "in_global_search": 1,
+   "label": "Employee Name",
+   "read_only": 1
+  },
+  {
+   "fieldname": "column_break_4",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "leave_type",
+   "fieldtype": "Link",
+   "ignore_user_permissions": 1,
+   "in_standard_filter": 1,
+   "label": "Leave Type",
+   "options": "Leave Type",
+   "reqd": 1,
+   "search_index": 1
+  },
+  {
+   "fetch_from": "employee.department",
+   "fieldname": "department",
+   "fieldtype": "Link",
+   "label": "Department",
+   "options": "Department",
+   "read_only": 1
+  },
+  {
+   "fieldname": "leave_balance",
+   "fieldtype": "Float",
+   "label": "Leave Balance Before Application",
+   "no_copy": 1,
+   "read_only": 1
+  },
+  {
+   "fieldname": "section_break_5",
+   "fieldtype": "Section Break"
+  },
+  {
+   "fieldname": "from_date",
+   "fieldtype": "Date",
+   "in_list_view": 1,
+   "label": "From Date",
+   "reqd": 1,
+   "search_index": 1
+  },
+  {
+   "fieldname": "to_date",
+   "fieldtype": "Date",
+   "label": "To Date",
+   "reqd": 1,
+   "search_index": 1
+  },
+  {
+   "default": "0",
+   "fieldname": "half_day",
+   "fieldtype": "Check",
+   "label": "Half Day"
+  },
+  {
+   "depends_on": "eval:doc.half_day && (doc.from_date != doc.to_date)",
+   "fieldname": "half_day_date",
+   "fieldtype": "Date",
+   "label": "Half Day Date"
+  },
+  {
+   "fieldname": "total_leave_days",
+   "fieldtype": "Float",
+   "in_list_view": 1,
+   "label": "Total Leave Days",
+   "no_copy": 1,
+   "precision": "1",
+   "read_only": 1
+  },
+  {
+   "fieldname": "column_break1",
+   "fieldtype": "Column Break",
+   "print_width": "50%",
+   "width": "50%"
+  },
+  {
+   "fieldname": "description",
+   "fieldtype": "Small Text",
+   "label": "Reason"
+  },
+  {
+   "fieldname": "section_break_7",
+   "fieldtype": "Section Break"
+  },
+  {
+   "fieldname": "leave_approver",
+   "fieldtype": "Link",
+   "label": "Leave Approver",
+   "options": "User"
+  },
+  {
+   "fieldname": "leave_approver_name",
+   "fieldtype": "Data",
+   "label": "Leave Approver Name",
+   "read_only": 1
+  },
+  {
+   "fieldname": "column_break_18",
+   "fieldtype": "Column Break"
+  },
+  {
+   "default": "Open",
+   "fieldname": "status",
+   "fieldtype": "Select",
+   "in_standard_filter": 1,
+   "label": "Status",
+   "no_copy": 1,
+   "options": "Open\nApproved\nRejected\nCancelled",
+   "permlevel": 1
+  },
+  {
+   "fieldname": "sb10",
+   "fieldtype": "Section Break"
+  },
+  {
+   "default": "Today",
+   "fieldname": "posting_date",
+   "fieldtype": "Date",
+   "label": "Posting Date",
+   "no_copy": 1,
+   "reqd": 1
+  },
+  {
+   "fieldname": "company",
+   "fieldtype": "Link",
+   "label": "Company",
+   "options": "Company",
+   "read_only": 1,
+   "remember_last_selected_value": 1,
+   "reqd": 1,
+   "fetch_from": "employee.company"
+  },
+  {
+   "allow_on_submit": 1,
+   "default": "1",
+   "fieldname": "follow_via_email",
+   "fieldtype": "Check",
+   "label": "Follow via Email",
+   "print_hide": 1
+  },
+  {
+   "fieldname": "column_break_17",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "salary_slip",
+   "fieldtype": "Link",
+   "label": "Salary Slip",
+   "options": "Salary Slip",
+   "print_hide": 1
+  },
+  {
+   "allow_on_submit": 1,
+   "fieldname": "letter_head",
+   "fieldtype": "Link",
+   "ignore_user_permissions": 1,
+   "label": "Letter Head",
+   "options": "Letter Head",
+   "print_hide": 1
+  },
+  {
+   "allow_on_submit": 1,
+   "fieldname": "color",
+   "fieldtype": "Color",
+   "label": "Color",
+   "print_hide": 1
+  },
+  {
+   "fieldname": "amended_from",
+   "fieldtype": "Link",
+   "ignore_user_permissions": 1,
+   "label": "Amended From",
+   "no_copy": 1,
+   "options": "Leave Application",
+   "print_hide": 1,
+   "read_only": 1
+  }
+ ],
+ "icon": "fa fa-calendar",
+ "idx": 1,
+ "is_submittable": 1,
+ "links": [],
+ "max_attachments": 3,
+ "modified": "2020-03-10 22:40:43.487721",
+ "modified_by": "Administrator",
+ "module": "HR",
+ "name": "Leave Application",
+ "owner": "Administrator",
+ "permissions": [
+  {
+   "create": 1,
+   "email": 1,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "Employee",
+   "share": 1,
+   "write": 1
+  },
+  {
+   "amend": 1,
+   "cancel": 1,
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "export": 1,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "HR Manager",
+   "set_user_permissions": 1,
+   "share": 1,
+   "submit": 1,
+   "write": 1
+  },
+  {
+   "permlevel": 1,
+   "read": 1,
+   "role": "All"
+  },
+  {
+   "amend": 1,
+   "cancel": 1,
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "HR User",
+   "set_user_permissions": 1,
+   "share": 1,
+   "submit": 1,
+   "write": 1
+  },
+  {
+   "amend": 1,
+   "cancel": 1,
+   "delete": 1,
+   "email": 1,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "Leave Approver",
+   "share": 1,
+   "submit": 1,
+   "write": 1
+  },
+  {
+   "permlevel": 1,
+   "read": 1,
+   "report": 1,
+   "role": "HR User",
+   "write": 1
+  },
+  {
+   "permlevel": 1,
+   "read": 1,
+   "report": 1,
+   "role": "Leave Approver",
+   "write": 1
+  }
+ ],
+ "search_fields": "employee,employee_name,leave_type,from_date,to_date,total_leave_days",
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "timeline_field": "employee",
+ "title_field": "employee_name"
+}
diff --git a/erpnext/hr/doctype/leave_application/leave_application.py b/erpnext/hr/doctype/leave_application/leave_application.py
index c441751..47b1bb7 100755
--- a/erpnext/hr/doctype/leave_application/leave_application.py
+++ b/erpnext/hr/doctype/leave_application/leave_application.py
@@ -374,7 +374,8 @@
 				leaves=self.total_leave_days * -1,
 				from_date=self.from_date,
 				to_date=self.to_date,
-				is_lwp=lwp
+				is_lwp=lwp,
+				holiday_list=get_holiday_list_for_employee(self.employee)
 			)
 			create_leave_ledger_entry(self, args, submit)
 
@@ -384,7 +385,9 @@
 			from_date=self.from_date,
 			to_date=expiry_date,
 			leaves=(date_diff(expiry_date, self.from_date) + 1) * -1,
-			is_lwp=lwp
+			is_lwp=lwp,
+			holiday_list=get_holiday_list_for_employee(self.employee),
+
 		)
 		create_leave_ledger_entry(self, args, submit)
 
@@ -410,7 +413,7 @@
 	return expiry[0]['to_date'] if expiry else None
 
 @frappe.whitelist()
-def get_number_of_leave_days(employee, leave_type, from_date, to_date, half_day = None, half_day_date = None):
+def get_number_of_leave_days(employee, leave_type, from_date, to_date, half_day = None, half_day_date = None, holiday_list = None):
 	number_of_days = 0
 	if cint(half_day) == 1:
 		if from_date == to_date:
@@ -424,7 +427,7 @@
 		number_of_days = date_diff(to_date, from_date) + 1
 
 	if not frappe.db.get_value("Leave Type", leave_type, "include_holiday"):
-		number_of_days = flt(number_of_days) - flt(get_holidays(employee, from_date, to_date))
+		number_of_days = flt(number_of_days) - flt(get_holidays(employee, from_date, to_date, holiday_list=holiday_list))
 	return number_of_days
 
 @frappe.whitelist()
@@ -575,7 +578,7 @@
 					{'name': leave_entry.transaction_name}, ['half_day_date'])
 
 			leave_days += get_number_of_leave_days(employee, leave_type,
-				leave_entry.from_date, leave_entry.to_date, half_day, half_day_date) * -1
+				leave_entry.from_date, leave_entry.to_date, half_day, half_day_date, holiday_list=leave_entry.holiday_list) * -1
 
 	return leave_days
 
@@ -589,7 +592,7 @@
 	''' Returns leave entries between from_date and to_date. '''
 	return frappe.db.sql("""
 		SELECT
-			employee, leave_type, from_date, to_date, leaves, transaction_name, transaction_type,
+			employee, leave_type, from_date, to_date, leaves, transaction_name, transaction_type, holiday_list,
 			is_carry_forward, is_expired
 		FROM `tabLeave Ledger Entry`
 		WHERE employee=%(employee)s AND leave_type=%(leave_type)s
@@ -607,9 +610,10 @@
 	}, as_dict=1)
 
 @frappe.whitelist()
-def get_holidays(employee, from_date, to_date):
+def get_holidays(employee, from_date, to_date, holiday_list = None):
 	'''get holidays between two dates for the given employee'''
-	holiday_list = get_holiday_list_for_employee(employee)
+	if not holiday_list:
+		holiday_list = get_holiday_list_for_employee(employee)
 
 	holidays = frappe.db.sql("""select count(distinct holiday_date) from `tabHoliday` h1, `tabHoliday List` h2
 		where h1.parent = h2.name and h1.holiday_date between %s and %s
diff --git a/erpnext/hr/doctype/leave_ledger_entry/leave_ledger_entry.json b/erpnext/hr/doctype/leave_ledger_entry/leave_ledger_entry.json
index 771e706..a5ac3f3 100644
--- a/erpnext/hr/doctype/leave_ledger_entry/leave_ledger_entry.json
+++ b/erpnext/hr/doctype/leave_ledger_entry/leave_ledger_entry.json
@@ -1,4 +1,5 @@
 {
+ "actions": [],
  "creation": "2019-05-09 15:47:39.760406",
  "doctype": "DocType",
  "engine": "InnoDB",
@@ -12,6 +13,7 @@
   "column_break_7",
   "from_date",
   "to_date",
+  "holiday_list",
   "is_carry_forward",
   "is_expired",
   "is_lwp",
@@ -98,11 +100,18 @@
    "fieldname": "is_lwp",
    "fieldtype": "Check",
    "label": "Is Leave Without Pay"
+  },
+  {
+   "fieldname": "holiday_list",
+   "fieldtype": "Link",
+   "label": "Holiday List",
+   "options": "Holiday List"
   }
  ],
  "in_create": 1,
  "is_submittable": 1,
- "modified": "2019-08-20 14:40:04.130799",
+ "links": [],
+ "modified": "2020-02-27 14:40:10.502605",
  "modified_by": "Administrator",
  "module": "HR",
  "name": "Leave Ledger Entry",
diff --git a/erpnext/hr/doctype/payroll_entry/payroll_entry.js b/erpnext/hr/doctype/payroll_entry/payroll_entry.js
index d25eb6d..da25d75 100644
--- a/erpnext/hr/doctype/payroll_entry/payroll_entry.js
+++ b/erpnext/hr/doctype/payroll_entry/payroll_entry.js
@@ -249,7 +249,7 @@
 
 let make_bank_entry = function (frm) {
 	var doc = frm.doc;
-	if (doc.company && doc.start_date && doc.end_date && doc.payment_account) {
+	if (doc.payment_account) {
 		return frappe.call({
 			doc: cur_frm.doc,
 			method: "make_payment_entry",
@@ -262,7 +262,8 @@
 			freeze_message: __("Creating Payment Entries......")
 		});
 	} else {
-		frappe.msgprint(__("Company, Payment Account, From Date and To Date is mandatory"));
+		frappe.msgprint(__("Payment Account is mandatory"));
+		frm.scroll_to_field('payment_account');
 	}
 };
 
diff --git a/erpnext/hr/doctype/payroll_period/payroll_period.json b/erpnext/hr/doctype/payroll_period/payroll_period.json
index c9bac09..c0fa506 100644
--- a/erpnext/hr/doctype/payroll_period/payroll_period.json
+++ b/erpnext/hr/doctype/payroll_period/payroll_period.json
@@ -1,401 +1,102 @@
 {
- "allow_copy": 0, 
- "allow_events_in_timeline": 0, 
- "allow_guest_to_view": 0, 
- "allow_import": 1, 
- "allow_rename": 0, 
- "autoname": "Prompt", 
- "beta": 0, 
- "creation": "2018-04-13 15:18:53.698553", 
- "custom": 0, 
- "docstatus": 0, 
- "doctype": "DocType", 
- "document_type": "", 
- "editable_grid": 1, 
- "engine": "InnoDB", 
+ "actions": [],
+ "allow_import": 1,
+ "autoname": "Prompt",
+ "creation": "2018-04-13 15:18:53.698553",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "company",
+  "column_break_2",
+  "start_date",
+  "end_date",
+  "section_break_5",
+  "periods"
+ ],
  "fields": [
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fetch_if_empty": 0, 
-   "fieldname": "company", 
-   "fieldtype": "Link", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Company", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Company", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 1, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "company",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "label": "Company",
+   "options": "Company",
+   "reqd": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fetch_if_empty": 0, 
-   "fieldname": "column_break_2", 
-   "fieldtype": "Column Break", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "column_break_2",
+   "fieldtype": "Column Break"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fetch_if_empty": 0, 
-   "fieldname": "start_date", 
-   "fieldtype": "Date", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Start Date", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 1, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "start_date",
+   "fieldtype": "Date",
+   "label": "Start Date",
+   "reqd": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fetch_if_empty": 0, 
-   "fieldname": "end_date", 
-   "fieldtype": "Date", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "End Date", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 1, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "end_date",
+   "fieldtype": "Date",
+   "label": "End Date",
+   "reqd": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fetch_if_empty": 0, 
-   "fieldname": "section_break_5", 
-   "fieldtype": "Section Break", 
-   "hidden": 1, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Payroll Periods", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "section_break_5",
+   "fieldtype": "Section Break",
+   "hidden": 1,
+   "label": "Payroll Periods"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fetch_if_empty": 0, 
-   "fieldname": "periods", 
-   "fieldtype": "Table", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Payroll Periods", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Payroll Period Date", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fetch_if_empty": 0, 
-   "fieldname": "section_break_7", 
-   "fieldtype": "Section Break", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Taxable Salary Slabs", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fetch_if_empty": 0, 
-   "fieldname": "taxable_salary_slabs", 
-   "fieldtype": "Table", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Taxable Salary Slabs", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Taxable Salary Slab", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fetch_if_empty": 0, 
-   "fieldname": "standard_tax_exemption_amount", 
-   "fieldtype": "Currency", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Standard Tax Exemption Amount", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
+   "fieldname": "periods",
+   "fieldtype": "Table",
+   "label": "Payroll Periods",
+   "options": "Payroll Period Date"
   }
- ], 
- "has_web_view": 0, 
- "hide_heading": 0, 
- "hide_toolbar": 0, 
- "idx": 0, 
- "image_view": 0, 
- "in_create": 0, 
- "is_submittable": 0, 
- "issingle": 0, 
- "istable": 0, 
- "max_attachments": 0, 
- "modified": "2019-04-26 01:45:03.160929", 
- "modified_by": "Administrator", 
- "module": "HR", 
- "name": "Payroll Period", 
- "name_case": "", 
- "owner": "Administrator", 
+ ],
+ "links": [],
+ "modified": "2020-03-18 18:13:23.859980",
+ "modified_by": "Administrator",
+ "module": "HR",
+ "name": "Payroll Period",
+ "owner": "Administrator",
  "permissions": [
   {
-   "amend": 0, 
-   "cancel": 0, 
-   "create": 1, 
-   "delete": 1, 
-   "email": 1, 
-   "export": 1, 
-   "if_owner": 0, 
-   "import": 0, 
-   "permlevel": 0, 
-   "print": 1, 
-   "read": 1, 
-   "report": 1, 
-   "role": "System Manager", 
-   "set_user_permissions": 0, 
-   "share": 1, 
-   "submit": 0, 
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "export": 1,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "System Manager",
+   "share": 1,
    "write": 1
-  }, 
+  },
   {
-   "amend": 0, 
-   "cancel": 0, 
-   "create": 1, 
-   "delete": 1, 
-   "email": 1, 
-   "export": 1, 
-   "if_owner": 0, 
-   "import": 0, 
-   "permlevel": 0, 
-   "print": 1, 
-   "read": 1, 
-   "report": 1, 
-   "role": "HR Manager", 
-   "set_user_permissions": 0, 
-   "share": 1, 
-   "submit": 0, 
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "export": 1,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "HR Manager",
+   "share": 1,
    "write": 1
-  }, 
+  },
   {
-   "amend": 0, 
-   "cancel": 0, 
-   "create": 1, 
-   "delete": 1, 
-   "email": 1, 
-   "export": 1, 
-   "if_owner": 0, 
-   "import": 0, 
-   "permlevel": 0, 
-   "print": 1, 
-   "read": 1, 
-   "report": 1, 
-   "role": "HR User", 
-   "set_user_permissions": 0, 
-   "share": 1, 
-   "submit": 0, 
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "export": 1,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "HR User",
+   "share": 1,
    "write": 1
   }
- ], 
- "quick_entry": 0, 
- "read_only": 0, 
- "read_only_onload": 0, 
- "show_name_in_global_search": 0, 
- "sort_field": "modified", 
- "sort_order": "DESC", 
- "track_changes": 1, 
- "track_seen": 0, 
- "track_views": 0
+ ],
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
 }
\ No newline at end of file
diff --git a/erpnext/hr/doctype/payroll_period/payroll_period.py b/erpnext/hr/doctype/payroll_period/payroll_period.py
index c176959..6956c38 100644
--- a/erpnext/hr/doctype/payroll_period/payroll_period.py
+++ b/erpnext/hr/doctype/payroll_period/payroll_period.py
@@ -45,8 +45,9 @@
 				+ _(") for {0}").format(self.company)
 			frappe.throw(msg)
 
-def get_payroll_period_days(start_date, end_date, employee):
-	company = frappe.db.get_value("Employee", employee, "company")
+def get_payroll_period_days(start_date, end_date, employee, company=None):
+	if not company:
+		company = frappe.db.get_value("Employee", employee, "company")
 	payroll_period = frappe.db.sql("""
 		select name, start_date, end_date
 		from `tabPayroll Period`
diff --git a/erpnext/hr/doctype/salary_component/salary_component.json b/erpnext/hr/doctype/salary_component/salary_component.json
index 986030d..97c46c8 100644
--- a/erpnext/hr/doctype/salary_component/salary_component.json
+++ b/erpnext/hr/doctype/salary_component/salary_component.json
@@ -1,264 +1,263 @@
 {
-    "allow_import": 1,
-    "allow_rename": 1,
-    "autoname": "field:salary_component",
-    "creation": "2016-06-30 15:42:43.631931",
-    "doctype": "DocType",
-    "document_type": "Setup",
-    "editable_grid": 1,
-    "engine": "InnoDB",
-    "field_order": [
-     "salary_component",
-     "salary_component_abbr",
-     "type",
-     "description",
-     "column_break_4",
-     "is_payable",
-     "depends_on_payment_days",
-     "is_tax_applicable",
-     "deduct_full_tax_on_selected_payroll_date",
-     "round_to_the_nearest_integer",
-     "statistical_component",
-     "do_not_include_in_total",
-     "disabled",
-     "flexible_benefits",
-     "is_flexible_benefit",
-     "max_benefit_amount",
-     "column_break_9",
-     "pay_against_benefit_claim",
-     "only_tax_impact",
-     "create_separate_payment_entry_against_benefit_claim",
-     "section_break_11",
-     "variable_based_on_taxable_salary",
-     "section_break_5",
-     "accounts",
-     "condition_and_formula",
-     "condition",
-     "amount",
-     "amount_based_on_formula",
-     "formula",
-     "column_break_28",
-     "help"
-    ],
-    "fields": [
-     {
-      "fieldname": "salary_component",
-      "fieldtype": "Data",
-      "in_list_view": 1,
-      "label": "Name",
-      "reqd": 1,
-      "unique": 1
-     },
-     {
-      "fieldname": "salary_component_abbr",
-      "fieldtype": "Data",
-      "in_list_view": 1,
-      "label": "Abbr",
-      "print_width": "120px",
-      "reqd": 1,
-      "width": "120px"
-     },
-     {
-      "fieldname": "type",
-      "fieldtype": "Select",
-      "in_standard_filter": 1,
-      "label": "Type",
-      "options": "Earning\nDeduction",
-      "reqd": 1
-     },
-     {
-      "default": "1",
-      "depends_on": "eval:doc.type == \"Earning\"",
-      "fieldname": "is_tax_applicable",
-      "fieldtype": "Check",
-      "label": "Is Tax Applicable"
-     },
-     {
-      "default": "1",
-      "fieldname": "is_payable",
-      "fieldtype": "Check",
-      "label": "Is Payable"
-     },
-     {
-      "default": "1",
-      "fieldname": "depends_on_payment_days",
-      "fieldtype": "Check",
-      "label": "Depends on Payment Days",
-      "print_hide": 1
-     },
-     {
-      "default": "0",
-      "fieldname": "do_not_include_in_total",
-      "fieldtype": "Check",
-      "label": "Do Not Include in Total"
-     },
-     {
-      "default": "0",
-      "depends_on": "is_tax_applicable",
-      "fieldname": "deduct_full_tax_on_selected_payroll_date",
-      "fieldtype": "Check",
-      "label": "Deduct Full Tax on Selected Payroll Date"
-     },
-     {
-      "fieldname": "column_break_4",
-      "fieldtype": "Column Break"
-     },
-     {
-      "default": "0",
-      "fieldname": "disabled",
-      "fieldtype": "Check",
-      "label": "Disabled"
-     },
-     {
-      "fieldname": "description",
-      "fieldtype": "Small Text",
-      "in_list_view": 1,
-      "label": "Description"
-     },
-     {
-      "default": "0",
-      "description": "If selected, the value specified or calculated in this component will not contribute to the earnings or deductions. However, it's value can be referenced by other components that can be added or deducted. ",
-      "fieldname": "statistical_component",
-      "fieldtype": "Check",
-      "label": "Statistical Component"
-     },
-     {
-      "depends_on": "eval:doc.type==\"Earning\" && doc.statistical_component!=1",
-      "fieldname": "flexible_benefits",
-      "fieldtype": "Section Break",
-      "label": "Flexible Benefits"
-     },
-     {
-      "default": "0",
-      "fieldname": "is_flexible_benefit",
-      "fieldtype": "Check",
-      "label": "Is Flexible Benefit"
-     },
-     {
-      "depends_on": "is_flexible_benefit",
-      "fieldname": "max_benefit_amount",
-      "fieldtype": "Currency",
-      "label": "Max Benefit Amount (Yearly)"
-     },
-     {
-      "fieldname": "column_break_9",
-      "fieldtype": "Column Break"
-     },
-     {
-      "default": "0",
-      "depends_on": "is_flexible_benefit",
-      "fieldname": "pay_against_benefit_claim",
-      "fieldtype": "Check",
-      "label": "Pay Against Benefit Claim"
-     },
-     {
-      "default": "0",
-      "depends_on": "eval:doc.is_flexible_benefit == 1 & doc.create_separate_payment_entry_against_benefit_claim !=1",
-      "fieldname": "only_tax_impact",
-      "fieldtype": "Check",
-      "label": "Only Tax Impact (Cannot Claim But Part of Taxable Income)"
-     },
-     {
-      "default": "0",
-      "depends_on": "eval:doc.is_flexible_benefit == 1 & doc.only_tax_impact !=1",
-      "fieldname": "create_separate_payment_entry_against_benefit_claim",
-      "fieldtype": "Check",
-      "label": "Create Separate Payment Entry Against Benefit Claim"
-     },
-     {
-      "depends_on": "eval:doc.type=='Deduction'",
-      "fieldname": "section_break_11",
-      "fieldtype": "Section Break"
-     },
-     {
-      "default": "0",
-      "fieldname": "variable_based_on_taxable_salary",
-      "fieldtype": "Check",
-      "label": "Variable Based On Taxable Salary"
-     },
-     {
-      "depends_on": "eval:doc.statistical_component != 1",
-      "fieldname": "section_break_5",
-      "fieldtype": "Section Break",
-      "label": "Accounts"
-     },
-     {
-      "fieldname": "accounts",
-      "fieldtype": "Table",
-      "label": "Accounts",
-      "options": "Salary Component Account"
-     },
-     {
-      "collapsible": 1,
-      "depends_on": "eval:doc.is_flexible_benefit != 1 && doc.variable_based_on_taxable_salary != 1",
-      "fieldname": "condition_and_formula",
-      "fieldtype": "Section Break",
-      "label": "Condition and Formula"
-     },
-     {
-      "fieldname": "condition",
-      "fieldtype": "Code",
-      "label": "Condition"
-     },
-     {
-      "default": "0",
-      "fieldname": "amount_based_on_formula",
-      "fieldtype": "Check",
-      "label": "Amount based on formula"
-     },
-     {
-      "depends_on": "amount_based_on_formula",
-      "fieldname": "formula",
-      "fieldtype": "Code",
-      "label": "Formula"
-     },
-     {
-      "depends_on": "eval:doc.amount_based_on_formula!==1",
-      "fieldname": "amount",
-      "fieldtype": "Currency",
-      "label": "Amount"
-     },
-     {
-      "fieldname": "column_break_28",
-      "fieldtype": "Column Break"
-     },
-     {
-      "fieldname": "help",
-      "fieldtype": "HTML",
-      "label": "Help",
-      "options": "<h3>Help</h3>\n\n<p>Notes:</p>\n\n<ol>\n<li>Use field <code>base</code> for using base salary of the Employee</li>\n<li>Use Salary Component abbreviations in conditions and formulas. <code>BS = Basic Salary</code></li>\n<li>Use field name for employee details in conditions and formulas. <code>Employment Type = employment_type</code><code>Branch = branch</code></li>\n<li>Use field name from Salary Slip in conditions and formulas. <code>Payment Days = payment_days</code><code>Leave without pay = leave_without_pay</code></li>\n<li>Direct Amount can also be entered based on Condtion. See example 3</li></ol>\n\n<h4>Examples</h4>\n<ol>\n<li>Calculating Basic Salary based on <code>base</code>\n<pre><code>Condition: base &lt; 10000</code></pre>\n<pre><code>Formula: base * .2</code></pre></li>\n<li>Calculating HRA based on Basic Salary<code>BS</code> \n<pre><code>Condition: BS &gt; 2000</code></pre>\n<pre><code>Formula: BS * .1</code></pre></li>\n<li>Calculating TDS based on Employment Type<code>employment_type</code> \n<pre><code>Condition: employment_type==\"Intern\"</code></pre>\n<pre><code>Amount: 1000</code></pre></li>\n</ol>"
-     },
-     {
-      "default": "0",
-      "fieldname": "round_to_the_nearest_integer",
-      "fieldtype": "Check",
-      "label": "Round to the Nearest Integer"
-     }
-    ],
-    "icon": "fa fa-flag",
-    "modified": "2019-06-05 11:34:14.231228",
-    "modified_by": "Administrator",
-    "module": "HR",
-    "name": "Salary Component",
-    "owner": "Administrator",
-    "permissions": [
-     {
-      "create": 1,
-      "delete": 1,
-      "email": 1,
-      "export": 1,
-      "print": 1,
-      "read": 1,
-      "report": 1,
-      "role": "HR User",
-      "share": 1,
-      "write": 1
-     },
-     {
-      "read": 1,
-      "role": "Employee"
-     }
-    ],
-    "sort_field": "modified",
-    "sort_order": "DESC"
-   }
\ No newline at end of file
+ "actions": [],
+ "allow_import": 1,
+ "allow_rename": 1,
+ "autoname": "field:salary_component",
+ "creation": "2016-06-30 15:42:43.631931",
+ "doctype": "DocType",
+ "document_type": "Setup",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "salary_component",
+  "salary_component_abbr",
+  "type",
+  "description",
+  "column_break_4",
+  "depends_on_payment_days",
+  "is_tax_applicable",
+  "deduct_full_tax_on_selected_payroll_date",
+  "variable_based_on_taxable_salary",
+  "exempted_from_income_tax",
+  "round_to_the_nearest_integer",
+  "statistical_component",
+  "do_not_include_in_total",
+  "disabled",
+  "flexible_benefits",
+  "is_flexible_benefit",
+  "max_benefit_amount",
+  "column_break_9",
+  "pay_against_benefit_claim",
+  "only_tax_impact",
+  "create_separate_payment_entry_against_benefit_claim",
+  "section_break_5",
+  "accounts",
+  "condition_and_formula",
+  "condition",
+  "amount",
+  "amount_based_on_formula",
+  "formula",
+  "column_break_28",
+  "help"
+ ],
+ "fields": [
+  {
+   "fieldname": "salary_component",
+   "fieldtype": "Data",
+   "in_list_view": 1,
+   "label": "Name",
+   "reqd": 1,
+   "unique": 1
+  },
+  {
+   "fieldname": "salary_component_abbr",
+   "fieldtype": "Data",
+   "in_list_view": 1,
+   "label": "Abbr",
+   "print_width": "120px",
+   "reqd": 1,
+   "width": "120px"
+  },
+  {
+   "fieldname": "type",
+   "fieldtype": "Select",
+   "in_standard_filter": 1,
+   "label": "Type",
+   "options": "Earning\nDeduction",
+   "reqd": 1
+  },
+  {
+   "default": "1",
+   "depends_on": "eval:doc.type == \"Earning\"",
+   "fieldname": "is_tax_applicable",
+   "fieldtype": "Check",
+   "label": "Is Tax Applicable"
+  },
+  {
+   "default": "1",
+   "fieldname": "depends_on_payment_days",
+   "fieldtype": "Check",
+   "label": "Depends on Payment Days",
+   "print_hide": 1
+  },
+  {
+   "default": "0",
+   "fieldname": "do_not_include_in_total",
+   "fieldtype": "Check",
+   "label": "Do Not Include in Total"
+  },
+  {
+   "default": "0",
+   "depends_on": "eval:doc.is_tax_applicable && doc.type=='Earning'",
+   "fieldname": "deduct_full_tax_on_selected_payroll_date",
+   "fieldtype": "Check",
+   "label": "Deduct Full Tax on Selected Payroll Date"
+  },
+  {
+   "fieldname": "column_break_4",
+   "fieldtype": "Column Break"
+  },
+  {
+   "default": "0",
+   "fieldname": "disabled",
+   "fieldtype": "Check",
+   "label": "Disabled"
+  },
+  {
+   "fieldname": "description",
+   "fieldtype": "Small Text",
+   "in_list_view": 1,
+   "label": "Description"
+  },
+  {
+   "default": "0",
+   "description": "If selected, the value specified or calculated in this component will not contribute to the earnings or deductions. However, it's value can be referenced by other components that can be added or deducted. ",
+   "fieldname": "statistical_component",
+   "fieldtype": "Check",
+   "label": "Statistical Component"
+  },
+  {
+   "depends_on": "eval:doc.type==\"Earning\" && doc.statistical_component!=1",
+   "fieldname": "flexible_benefits",
+   "fieldtype": "Section Break",
+   "label": "Flexible Benefits"
+  },
+  {
+   "default": "0",
+   "fieldname": "is_flexible_benefit",
+   "fieldtype": "Check",
+   "label": "Is Flexible Benefit"
+  },
+  {
+   "depends_on": "is_flexible_benefit",
+   "fieldname": "max_benefit_amount",
+   "fieldtype": "Currency",
+   "label": "Max Benefit Amount (Yearly)"
+  },
+  {
+   "fieldname": "column_break_9",
+   "fieldtype": "Column Break"
+  },
+  {
+   "default": "0",
+   "depends_on": "is_flexible_benefit",
+   "fieldname": "pay_against_benefit_claim",
+   "fieldtype": "Check",
+   "label": "Pay Against Benefit Claim"
+  },
+  {
+   "default": "0",
+   "depends_on": "eval:doc.is_flexible_benefit == 1 & doc.create_separate_payment_entry_against_benefit_claim !=1",
+   "fieldname": "only_tax_impact",
+   "fieldtype": "Check",
+   "label": "Only Tax Impact (Cannot Claim But Part of Taxable Income)"
+  },
+  {
+   "default": "0",
+   "depends_on": "eval:doc.is_flexible_benefit == 1 & doc.only_tax_impact !=1",
+   "fieldname": "create_separate_payment_entry_against_benefit_claim",
+   "fieldtype": "Check",
+   "label": "Create Separate Payment Entry Against Benefit Claim"
+  },
+  {
+   "default": "0",
+   "depends_on": "eval:doc.type == \"Deduction\"",
+   "fieldname": "variable_based_on_taxable_salary",
+   "fieldtype": "Check",
+   "label": "Variable Based On Taxable Salary"
+  },
+  {
+   "depends_on": "eval:doc.statistical_component != 1",
+   "fieldname": "section_break_5",
+   "fieldtype": "Section Break",
+   "label": "Accounts"
+  },
+  {
+   "fieldname": "accounts",
+   "fieldtype": "Table",
+   "label": "Accounts",
+   "options": "Salary Component Account"
+  },
+  {
+   "collapsible": 1,
+   "depends_on": "eval:doc.is_flexible_benefit != 1 && doc.variable_based_on_taxable_salary != 1",
+   "fieldname": "condition_and_formula",
+   "fieldtype": "Section Break",
+   "label": "Condition and Formula"
+  },
+  {
+   "fieldname": "condition",
+   "fieldtype": "Code",
+   "label": "Condition"
+  },
+  {
+   "default": "0",
+   "fieldname": "amount_based_on_formula",
+   "fieldtype": "Check",
+   "label": "Amount based on formula"
+  },
+  {
+   "depends_on": "amount_based_on_formula",
+   "fieldname": "formula",
+   "fieldtype": "Code",
+   "label": "Formula"
+  },
+  {
+   "depends_on": "eval:doc.amount_based_on_formula!==1",
+   "fieldname": "amount",
+   "fieldtype": "Currency",
+   "label": "Amount"
+  },
+  {
+   "fieldname": "column_break_28",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "help",
+   "fieldtype": "HTML",
+   "label": "Help",
+   "options": "<h3>Help</h3>\n\n<p>Notes:</p>\n\n<ol>\n<li>Use field <code>base</code> for using base salary of the Employee</li>\n<li>Use Salary Component abbreviations in conditions and formulas. <code>BS = Basic Salary</code></li>\n<li>Use field name for employee details in conditions and formulas. <code>Employment Type = employment_type</code><code>Branch = branch</code></li>\n<li>Use field name from Salary Slip in conditions and formulas. <code>Payment Days = payment_days</code><code>Leave without pay = leave_without_pay</code></li>\n<li>Direct Amount can also be entered based on Condtion. See example 3</li></ol>\n\n<h4>Examples</h4>\n<ol>\n<li>Calculating Basic Salary based on <code>base</code>\n<pre><code>Condition: base &lt; 10000</code></pre>\n<pre><code>Formula: base * .2</code></pre></li>\n<li>Calculating HRA based on Basic Salary<code>BS</code> \n<pre><code>Condition: BS &gt; 2000</code></pre>\n<pre><code>Formula: BS * .1</code></pre></li>\n<li>Calculating TDS based on Employment Type<code>employment_type</code> \n<pre><code>Condition: employment_type==\"Intern\"</code></pre>\n<pre><code>Amount: 1000</code></pre></li>\n</ol>"
+  },
+  {
+   "default": "0",
+   "fieldname": "round_to_the_nearest_integer",
+   "fieldtype": "Check",
+   "label": "Round to the Nearest Integer"
+  },
+  {
+   "default": "0",
+   "depends_on": "eval:doc.type == \"Deduction\" && !doc.variable_based_on_taxable_salary",
+   "description": "If checked, the full amount will be deducted from taxable income before calculating income tax without any declaration or proof submission.",
+   "fieldname": "exempted_from_income_tax",
+   "fieldtype": "Check",
+   "label": "Exempted from Income Tax"
+  }
+ ],
+ "icon": "fa fa-flag",
+ "links": [],
+ "modified": "2020-04-28 15:46:45.252945",
+ "modified_by": "Administrator",
+ "module": "HR",
+ "name": "Salary Component",
+ "owner": "Administrator",
+ "permissions": [
+  {
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "export": 1,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "HR User",
+   "share": 1,
+   "write": 1
+  },
+  {
+   "read": 1,
+   "role": "Employee"
+  }
+ ],
+ "sort_field": "modified",
+ "sort_order": "DESC"
+}
\ No newline at end of file
diff --git a/erpnext/hr/doctype/salary_component/test_records.json b/erpnext/hr/doctype/salary_component/test_records.json
index 7b22b48..104b44f 100644
--- a/erpnext/hr/doctype/salary_component/test_records.json
+++ b/erpnext/hr/doctype/salary_component/test_records.json
@@ -3,14 +3,12 @@
 		"doctype": "Salary Component",
 		"salary_component": "_Test Basic Salary",
 		"type": "Earning",
-		"is_payable": 1,
 		"is_tax_applicable": 1
 	},
 	{
 		"doctype": "Salary Component",
 		"salary_component": "_Test Allowance",
 		"type": "Earning",
-		"is_payable": 1,
 		"is_tax_applicable": 1
 	},
 	{
@@ -27,14 +25,12 @@
 		"doctype": "Salary Component",
 		"salary_component": "Basic",
 		"type": "Earning",
-		"is_payable": 1,
 		"is_tax_applicable": 1
 	},
 	{
 		"doctype": "Salary Component",
 		"salary_component": "Leave Encashment",
 		"type": "Earning",
-		"is_payable": 1,
 		"is_tax_applicable": 1
 	}
 ]
\ No newline at end of file
diff --git a/erpnext/hr/doctype/salary_component/test_salary_component.py b/erpnext/hr/doctype/salary_component/test_salary_component.py
index 965cc9e..4f7db0c 100644
--- a/erpnext/hr/doctype/salary_component/test_salary_component.py
+++ b/erpnext/hr/doctype/salary_component/test_salary_component.py
@@ -18,6 +18,5 @@
 				"doctype": "Salary Component",
 				"salary_component": component_name,
 				"type": args.get("type") or "Earning",
-				"is_payable": args.get("is_payable") or 1,
 				"is_tax_applicable": args.get("is_tax_applicable") or 1
 			}).insert()
diff --git a/erpnext/hr/doctype/salary_detail/salary_detail.json b/erpnext/hr/doctype/salary_detail/salary_detail.json
index bde735d..545f56a 100644
--- a/erpnext/hr/doctype/salary_detail/salary_detail.json
+++ b/erpnext/hr/doctype/salary_detail/salary_detail.json
@@ -12,6 +12,7 @@
   "deduct_full_tax_on_selected_payroll_date",
   "depends_on_payment_days",
   "is_tax_applicable",
+  "exempted_from_income_tax",
   "is_flexible_benefit",
   "variable_based_on_taxable_salary",
   "section_break_2",
@@ -62,6 +63,7 @@
   },
   {
    "default": "0",
+   "depends_on": "eval:doc.parentfield=='earnings'",
    "fetch_from": "salary_component.is_tax_applicable",
    "fieldname": "is_tax_applicable",
    "fieldtype": "Check",
@@ -71,6 +73,7 @@
   },
   {
    "default": "0",
+   "depends_on": "eval:doc.parentfield=='earnings'",
    "fetch_from": "salary_component.is_flexible_benefit",
    "fieldname": "is_flexible_benefit",
    "fieldtype": "Check",
@@ -80,6 +83,7 @@
   },
   {
    "default": "0",
+   "depends_on": "eval:doc.parentfield=='deductions'",
    "fetch_from": "salary_component.variable_based_on_taxable_salary",
    "fieldname": "variable_based_on_taxable_salary",
    "fieldtype": "Check",
@@ -187,11 +191,20 @@
    "fieldtype": "HTML",
    "label": "Condition and Formula Help",
    "options": "<h3>Condition and Formula Help</h3>\n\n<p>Notes:</p>\n\n<ol>\n<li>Use field <code>base</code> for using base salary of the Employee</li>\n<li>Use Salary Component abbreviations in conditions and formulas. <code>BS = Basic Salary</code></li>\n<li>Use field name for employee details in conditions and formulas. <code>Employment Type = employment_type</code><code>Branch = branch</code></li>\n<li>Use field name from Salary Slip in conditions and formulas. <code>Payment Days = payment_days</code><code>Leave without pay = leave_without_pay</code></li>\n<li>Direct Amount can also be entered based on Condtion. See example 3</li></ol>\n\n<h4>Examples</h4>\n<ol>\n<li>Calculating Basic Salary based on <code>base</code>\n<pre><code>Condition: base &lt; 10000</code></pre>\n<pre><code>Formula: base * .2</code></pre></li>\n<li>Calculating HRA based on Basic Salary<code>BS</code> \n<pre><code>Condition: BS &gt; 2000</code></pre>\n<pre><code>Formula: BS * .1</code></pre></li>\n<li>Calculating TDS based on Employment Type<code>employment_type</code> \n<pre><code>Condition: employment_type==\"Intern\"</code></pre>\n<pre><code>Amount: 1000</code></pre></li>\n</ol>"
+  },
+  {
+   "default": "0",
+   "depends_on": "eval:doc.parentfield=='deductions'",
+   "fetch_from": "salary_component.exempted_from_income_tax",
+   "fieldname": "exempted_from_income_tax",
+   "fieldtype": "Check",
+   "label": "Exempted from Income Tax",
+   "read_only": 1
   }
  ],
  "istable": 1,
  "links": [],
- "modified": "2019-12-31 17:15:25.646689",
+ "modified": "2020-04-24 20:00:16.475295",
  "modified_by": "Administrator",
  "module": "HR",
  "name": "Salary Detail",
diff --git a/erpnext/hr/doctype/salary_slip/salary_slip.js b/erpnext/hr/doctype/salary_slip/salary_slip.js
index f430eee..1c4d4e3 100644
--- a/erpnext/hr/doctype/salary_slip/salary_slip.js
+++ b/erpnext/hr/doctype/salary_slip/salary_slip.js
@@ -51,7 +51,7 @@
 	},
 
 	end_date: function(frm) {
-		frm.events.get_emp_and_leave_details(frm);
+		frm.events.get_emp_and_working_day_details(frm);
 	},
 
 	set_end_date: function(frm){
@@ -86,7 +86,7 @@
 
 	salary_slip_based_on_timesheet: function(frm) {
 		frm.trigger("toggle_fields");
-		frm.events.get_emp_and_leave_details(frm);
+		frm.events.get_emp_and_working_day_details(frm);
 	},
 
 	payroll_frequency: function(frm) {
@@ -95,15 +95,14 @@
 	},
 
 	employee: function(frm) {
-		frm.events.get_emp_and_leave_details(frm);
+		frm.events.get_emp_and_working_day_details(frm);
 	},
 
 	leave_without_pay: function(frm){
 		if (frm.doc.employee && frm.doc.start_date && frm.doc.end_date) {
 			return frappe.call({
-				method: 'process_salary_based_on_leave',
+				method: 'process_salary_based_on_working_days',
 				doc: frm.doc,
-				args: {"lwp": frm.doc.leave_without_pay},
 				callback: function(r, rt) {
 					frm.refresh();
 				}
@@ -115,12 +114,12 @@
 		frm.toggle_display(['hourly_wages', 'timesheets'], cint(frm.doc.salary_slip_based_on_timesheet)===1);
 
 		frm.toggle_display(['payment_days', 'total_working_days', 'leave_without_pay'],
-			frm.doc.payroll_frequency!="");
+			frm.doc.payroll_frequency != "");
 	},
 
-	get_emp_and_leave_details: function(frm) {
+	get_emp_and_working_day_details: function(frm) {
 		return frappe.call({
-			method: 'get_emp_and_leave_details',
+			method: 'get_emp_and_working_day_details',
 			doc: frm.doc,
 			callback: function(r, rt) {
 				frm.refresh();
diff --git a/erpnext/hr/doctype/salary_slip/salary_slip.json b/erpnext/hr/doctype/salary_slip/salary_slip.json
index 097d3a0..54a8164 100644
--- a/erpnext/hr/doctype/salary_slip/salary_slip.json
+++ b/erpnext/hr/doctype/salary_slip/salary_slip.json
@@ -11,20 +11,20 @@
   "employee_name",
   "department",
   "designation",
+  "branch",
   "column_break1",
-  "company",
+  "status",
   "journal_entry",
   "payroll_entry",
+  "company",
   "letter_head",
-  "branch",
-  "status",
   "section_break_10",
   "salary_slip_based_on_timesheet",
-  "payroll_frequency",
   "start_date",
   "end_date",
   "column_break_15",
   "salary_structure",
+  "payroll_frequency",
   "total_working_days",
   "leave_without_pay",
   "payment_days",
@@ -309,6 +309,7 @@
   {
    "fieldname": "earning",
    "fieldtype": "Column Break",
+   "label": "Earning",
    "oldfieldtype": "Column Break",
    "width": "50%"
   },
@@ -323,6 +324,7 @@
   {
    "fieldname": "deduction",
    "fieldtype": "Column Break",
+   "label": "Deduction",
    "oldfieldtype": "Column Break",
    "width": "50%"
   },
@@ -463,7 +465,7 @@
  "idx": 9,
  "is_submittable": 1,
  "links": [],
- "modified": "2020-04-09 20:02:53.159827",
+ "modified": "2020-04-14 20:02:53.159827", 
  "modified_by": "Administrator",
  "module": "HR",
  "name": "Salary Slip",
diff --git a/erpnext/hr/doctype/salary_slip/salary_slip.py b/erpnext/hr/doctype/salary_slip/salary_slip.py
index 223c4e3..db93f31 100644
--- a/erpnext/hr/doctype/salary_slip/salary_slip.py
+++ b/erpnext/hr/doctype/salary_slip/salary_slip.py
@@ -5,7 +5,7 @@
 import frappe, erpnext
 import datetime, math
 
-from frappe.utils import add_days, cint, cstr, flt, getdate, rounded, date_diff, money_in_words
+from frappe.utils import add_days, cint, cstr, flt, getdate, rounded, date_diff, money_in_words, formatdate
 from frappe.model.naming import make_autoname
 
 from frappe import msgprint, _
@@ -44,9 +44,9 @@
 
 		if not (len(self.get("earnings")) or len(self.get("deductions"))):
 			# get details from salary structure
-			self.get_emp_and_leave_details()
+			self.get_emp_and_working_day_details()
 		else:
-			self.get_leave_details(lwp = self.leave_without_pay)
+			self.get_working_days_details(lwp = self.leave_without_pay)
 
 		self.calculate_net_pay()
 
@@ -117,7 +117,7 @@
 			self.start_date = date_details.start_date
 			self.end_date = date_details.end_date
 
-	def get_emp_and_leave_details(self):
+	def get_emp_and_working_day_details(self):
 		'''First time, load all the components from salary structure'''
 		if self.employee:
 			self.set("earnings", [])
@@ -129,7 +129,8 @@
 			joining_date, relieving_date = frappe.get_cached_value("Employee", self.employee,
 				["date_of_joining", "relieving_date"])
 
-			self.get_leave_details(joining_date, relieving_date)
+			#getin leave details
+			self.get_working_days_details(joining_date, relieving_date)
 			struct = self.check_sal_struct(joining_date, relieving_date)
 
 			if struct:
@@ -188,10 +189,9 @@
 
 		make_salary_slip(self._salary_structure_doc.name, self)
 
-	def get_leave_details(self, joining_date=None, relieving_date=None, lwp=None, for_preview=0):
-		if not joining_date:
-			joining_date, relieving_date = frappe.get_cached_value("Employee", self.employee,
-				["date_of_joining", "relieving_date"])
+	def get_working_days_details(self, joining_date=None, relieving_date=None, lwp=None, for_preview=0):
+		payroll_based_on = frappe.db.get_value("HR Settings", None, "payroll_based_on")
+		include_holidays_in_total_working_days = frappe.db.get_single_value("HR Settings", "include_holidays_in_total_working_days")
 
 		working_days = date_diff(self.end_date, self.start_date) + 1
 		if for_preview:
@@ -200,24 +200,42 @@
 			return
 
 		holidays = self.get_holidays_for_employee(self.start_date, self.end_date)
-		actual_lwp = self.calculate_lwp(holidays, working_days)
-		if not cint(frappe.db.get_value("HR Settings", None, "include_holidays_in_total_working_days")):
+		
+		if not cint(include_holidays_in_total_working_days):
 			working_days -= len(holidays)
 			if working_days < 0:
 				frappe.throw(_("There are more holidays than working days this month."))
 
+		if not payroll_based_on:
+			frappe.throw(_("Please set Payroll based on in HR settings"))
+		
+		if payroll_based_on == "Attendance":
+			actual_lwp = self.calculate_lwp_based_on_attendance(holidays)
+		else:
+			actual_lwp = self.calculate_lwp_based_on_leave_application(holidays, working_days)
+
 		if not lwp:
 			lwp = actual_lwp
 		elif lwp != actual_lwp:
-			frappe.msgprint(_("Leave Without Pay does not match with approved Leave Application records"))
+			frappe.msgprint(_("Leave Without Pay does not match with approved {} records")
+				.format(payroll_based_on))
 
-		self.total_working_days = working_days
 		self.leave_without_pay = lwp
+		self.total_working_days = working_days
 
-		payment_days = flt(self.get_payment_days(joining_date, relieving_date)) - flt(lwp)
-		self.payment_days = payment_days > 0 and payment_days or 0
+		payment_days = self.get_payment_days(joining_date,
+			relieving_date, include_holidays_in_total_working_days)
 
-	def get_payment_days(self, joining_date, relieving_date):
+		if flt(payment_days) > flt(lwp):
+			self.payment_days = flt(payment_days) - flt(lwp)
+		else:
+			self.payment_days = 0
+
+	def get_payment_days(self, joining_date, relieving_date, include_holidays_in_total_working_days):
+		if not joining_date:
+			joining_date, relieving_date = frappe.get_cached_value("Employee", self.employee,
+				["date_of_joining", "relieving_date"])
+
 		start_date = getdate(self.start_date)
 		if joining_date:
 			if getdate(self.start_date) <= joining_date <= getdate(self.end_date):
@@ -235,9 +253,10 @@
 
 		payment_days = date_diff(end_date, start_date) + 1
 
-		if not cint(frappe.db.get_value("HR Settings", None, "include_holidays_in_total_working_days")):
+		if not cint(include_holidays_in_total_working_days):
 			holidays = self.get_holidays_for_employee(start_date, end_date)
 			payment_days -= len(holidays)
+
 		return payment_days
 
 	def get_holidays_for_employee(self, start_date, end_date):
@@ -256,27 +275,67 @@
 
 		return holidays
 
-	def calculate_lwp(self, holidays, working_days):
+	def calculate_lwp_based_on_leave_application(self, holidays, working_days):
 		lwp = 0
 		holidays = "','".join(holidays)
+		daily_wages_fraction_for_half_day = \
+			flt(frappe.db.get_value("HR Settings", None, "daily_wages_fraction_for_half_day")) or 0.5
+
 		for d in range(working_days):
 			dt = add_days(cstr(getdate(self.start_date)), d)
 			leave = frappe.db.sql("""
 				SELECT t1.name,
-					CASE WHEN t1.half_day_date = %(dt)s or t1.to_date = t1.from_date
+					CASE WHEN (t1.half_day_date = %(dt)s or t1.to_date = t1.from_date)
 					THEN t1.half_day else 0 END
 				FROM `tabLeave Application` t1, `tabLeave Type` t2
 				WHERE t2.name = t1.leave_type
 				AND t2.is_lwp = 1
 				AND t1.docstatus = 1
 				AND t1.employee = %(employee)s
-				AND CASE WHEN t2.include_holiday != 1 THEN %(dt)s not in ('{0}') and %(dt)s between from_date and to_date and ifnull(t1.salary_slip, '') = ''
-				WHEN t2.include_holiday THEN %(dt)s between from_date and to_date and ifnull(t1.salary_slip, '') = ''
-				END
+				AND ifnull(t1.salary_slip, '') = ''
+				AND CASE
+					WHEN t2.include_holiday != 1
+						THEN %(dt)s not in ('{0}') and %(dt)s between from_date and to_date
+					WHEN t2.include_holiday
+						THEN %(dt)s between from_date and to_date
+					END
 				""".format(holidays), {"employee": self.employee, "dt": dt})
 
 			if leave:
-				lwp = cint(leave[0][1]) and (lwp + 0.5) or (lwp + 1)
+				is_half_day_leave = cint(leave[0][1])
+				lwp += (1 - daily_wages_fraction_for_half_day) if is_half_day_leave else 1
+
+		return lwp
+	
+	def calculate_lwp_based_on_attendance(self, holidays):
+		lwp = 0
+
+		daily_wages_fraction_for_half_day = \
+			flt(frappe.db.get_value("HR Settings", None, "daily_wages_fraction_for_half_day")) or 0.5
+
+		lwp_leave_types = dict(frappe.get_all("Leave Type", {"is_lwp": 1}, ["name", "include_holiday"], as_list=1))
+
+		attendances = frappe.db.sql('''
+			SELECT attendance_date, status, leave_type
+			FROM `tabAttendance`
+			WHERE
+				status in ("Absent", "Half Day", "On leave")
+				AND employee = %s
+				AND docstatus = 1
+				AND attendance_date between %s and %s
+		''', values=(self.employee, self.start_date, self.end_date), as_dict=1)
+		
+		for d in attendances:
+			if d.status in ('Half Day', 'On Leave') and d.leave_type and d.leave_type not in lwp_leave_types:
+				continue
+
+			if formatdate(d.attendance_date, "yyyy-mm-dd") in holidays:
+				if d.status == "Absent" or \
+					(d.leave_type and d.leave_type in lwp_leave_types and not lwp_leave_types[d.leave_type]):
+						continue
+
+			lwp += (1 - daily_wages_fraction_for_half_day) if d.status == "Half Day" else 1
+
 		return lwp
 
 	def add_earning_for_hourly_wages(self, doc, salary_component, amount):
@@ -451,7 +510,8 @@
 					'is_flexible_benefit': struct_row.is_flexible_benefit,
 					'variable_based_on_taxable_salary': struct_row.variable_based_on_taxable_salary,
 					'deduct_full_tax_on_selected_payroll_date': struct_row.deduct_full_tax_on_selected_payroll_date,
-					'additional_amount': amount if struct_row.get("is_additional_component") else 0
+					'additional_amount': amount if struct_row.get("is_additional_component") else 0,
+					'exempted_from_income_tax': struct_row.exempted_from_income_tax
 				})
 		else:
 			if struct_row.get("is_additional_component"):
@@ -482,20 +542,23 @@
 		return self.calculate_variable_tax(payroll_period, tax_component)
 
 	def calculate_variable_tax(self, payroll_period, tax_component):
+		# get Tax slab from salary structure assignment for the employee and payroll period
+		tax_slab = self.get_income_tax_slabs(payroll_period)
+
 		# get remaining numbers of sub-period (period for which one salary is processed)
 		remaining_sub_periods = get_period_factor(self.employee,
 			self.start_date, self.end_date, self.payroll_frequency, payroll_period)[1]
-
 		# get taxable_earnings, paid_taxes for previous period
-		previous_taxable_earnings = self.get_taxable_earnings_for_prev_period(payroll_period.start_date, self.start_date)
+		previous_taxable_earnings = self.get_taxable_earnings_for_prev_period(payroll_period.start_date,
+			self.start_date, tax_slab.allow_tax_exemption)
 		previous_total_paid_taxes = self.get_tax_paid_in_period(payroll_period.start_date, self.start_date, tax_component)
 
 		# get taxable_earnings for current period (all days)
-		current_taxable_earnings = self.get_taxable_earnings()
+		current_taxable_earnings = self.get_taxable_earnings(tax_slab.allow_tax_exemption)
 		future_structured_taxable_earnings = current_taxable_earnings.taxable_earnings * (math.ceil(remaining_sub_periods) - 1)
 
 		# get taxable_earnings, addition_earnings for current actual payment days
-		current_taxable_earnings_for_payment_days = self.get_taxable_earnings(based_on_payment_days=1)
+		current_taxable_earnings_for_payment_days = self.get_taxable_earnings(tax_slab.allow_tax_exemption, based_on_payment_days=1)
 		current_structured_taxable_earnings = current_taxable_earnings_for_payment_days.taxable_earnings
 		current_additional_earnings = current_taxable_earnings_for_payment_days.additional_income
 		current_additional_earnings_with_full_tax = current_taxable_earnings_for_payment_days.additional_income_with_full_tax
@@ -507,23 +570,27 @@
 			unclaimed_taxable_benefits += current_taxable_earnings_for_payment_days.flexi_benefits
 
 		# Total exemption amount based on tax exemption declaration
-		total_exemption_amount, other_incomes = self.get_total_exemption_amount_and_other_incomes(payroll_period)
+		total_exemption_amount = self.get_total_exemption_amount(payroll_period, tax_slab)
+
+		#Employee Other Incomes
+		other_incomes = self.get_income_form_other_sources(payroll_period) or 0.0
 
 		# Total taxable earnings including additional and other incomes
 		total_taxable_earnings = previous_taxable_earnings + current_structured_taxable_earnings + future_structured_taxable_earnings \
 			+ current_additional_earnings + other_incomes + unclaimed_taxable_benefits - total_exemption_amount
-
+		
 		# Total taxable earnings without additional earnings with full tax
 		total_taxable_earnings_without_full_tax_addl_components = total_taxable_earnings - current_additional_earnings_with_full_tax
 
 		# Structured tax amount
-		total_structured_tax_amount = self.calculate_tax_by_tax_slab(payroll_period, total_taxable_earnings_without_full_tax_addl_components)
+		total_structured_tax_amount = self.calculate_tax_by_tax_slab(
+			total_taxable_earnings_without_full_tax_addl_components, tax_slab)
 		current_structured_tax_amount = (total_structured_tax_amount - previous_total_paid_taxes) / remaining_sub_periods
-
+		
 		# Total taxable earnings with additional earnings with full tax
 		full_tax_on_additional_earnings = 0.0
 		if current_additional_earnings_with_full_tax:
-			total_tax_amount = self.calculate_tax_by_tax_slab(payroll_period, total_taxable_earnings)
+			total_tax_amount = self.calculate_tax_by_tax_slab(total_taxable_earnings, tax_slab)
 			full_tax_on_additional_earnings = total_tax_amount - total_structured_tax_amount
 
 		current_tax_amount = current_structured_tax_amount + full_tax_on_additional_earnings
@@ -532,12 +599,30 @@
 
 		return current_tax_amount
 
-	def get_taxable_earnings_for_prev_period(self, start_date, end_date):
+	def get_income_tax_slabs(self, payroll_period):
+		income_tax_slab, ss_assignment_name = frappe.db.get_value("Salary Structure Assignment",
+			{"employee": self.employee, "salary_structure": self.salary_structure, "docstatus": 1}, ["income_tax_slab", 'name'])
+
+		if not income_tax_slab:
+			frappe.throw(_("Income Tax Slab not set in Salary Structure Assignment: {0}").format(ss_assignment_name))
+
+		income_tax_slab_doc = frappe.get_doc("Income Tax Slab", income_tax_slab)
+		if income_tax_slab_doc.disabled:
+			frappe.throw(_("Income Tax Slab: {0} is disabled").format(income_tax_slab))
+
+		if getdate(income_tax_slab_doc.effective_from) > getdate(payroll_period.start_date):
+			frappe.throw(_("Income Tax Slab must be effective on or before Payroll Period Start Date: {0}")
+				.format(payroll_period.start_date))
+
+		return income_tax_slab_doc
+
+
+	def get_taxable_earnings_for_prev_period(self, start_date, end_date, allow_tax_exemption=False):
 		taxable_earnings = frappe.db.sql("""
 			select sum(sd.amount)
 			from
 				`tabSalary Detail` sd join `tabSalary Slip` ss on sd.parent=ss.name
-			where
+			where 
 				sd.parentfield='earnings'
 				and sd.is_tax_applicable=1
 				and is_flexible_benefit=0
@@ -550,7 +635,30 @@
 				"from_date": start_date,
 				"to_date": end_date
 			})
-		return flt(taxable_earnings[0][0]) if taxable_earnings else 0
+		taxable_earnings = flt(taxable_earnings[0][0]) if taxable_earnings else 0
+
+		exempted_amount = 0
+		if allow_tax_exemption:
+			exempted_amount = frappe.db.sql("""
+				select sum(sd.amount)
+				from
+					`tabSalary Detail` sd join `tabSalary Slip` ss on sd.parent=ss.name
+				where
+					sd.parentfield='deductions'
+					and sd.exempted_from_income_tax=1
+					and is_flexible_benefit=0
+					and ss.docstatus=1
+					and ss.employee=%(employee)s
+					and ss.start_date between %(from_date)s and %(to_date)s
+					and ss.end_date between %(from_date)s and %(to_date)s
+				""", {
+					"employee": self.employee,
+					"from_date": start_date,
+					"to_date": end_date
+				})
+			exempted_amount = flt(exempted_amount[0][0]) if exempted_amount else 0
+
+		return taxable_earnings - exempted_amount
 
 	def get_tax_paid_in_period(self, start_date, end_date, tax_component):
 		# find total_tax_paid, tax paid for benefit, additional_salary
@@ -576,7 +684,7 @@
 
 		return total_tax_paid
 
-	def get_taxable_earnings(self, based_on_payment_days=0):
+	def get_taxable_earnings(self, allow_tax_exemption=False, based_on_payment_days=0):
 		joining_date, relieving_date = frappe.get_cached_value("Employee", self.employee,
 			["date_of_joining", "relieving_date"])
 
@@ -610,6 +718,14 @@
 				else:
 					taxable_earnings += amount
 
+		if allow_tax_exemption:
+			for ded in self.deductions:
+				if ded.exempted_from_income_tax:
+					amount = ded.amount
+					if based_on_payment_days:
+						amount = self.get_amount_based_on_payment_days(ded, joining_date, relieving_date)[0]
+					taxable_earnings -= flt(amount)
+
 		return frappe._dict({
 			"taxable_earnings": taxable_earnings,
 			"additional_income": additional_income,
@@ -672,40 +788,63 @@
 
 		return total_benefits_paid - total_benefits_claimed
 
-	def get_total_exemption_amount_and_other_incomes(self, payroll_period):
-		total_exemption_amount, other_incomes = 0, 0
-		if self.deduct_tax_for_unsubmitted_tax_exemption_proof:
-			exemption_proof = frappe.db.get_value("Employee Tax Exemption Proof Submission",
-				{"employee": self.employee, "payroll_period": payroll_period.name, "docstatus": 1},
-				["exemption_amount", "income_from_other_sources"])
-			if exemption_proof:
-				total_exemption_amount, other_incomes = exemption_proof
-		else:
-			declaration = frappe.db.get_value("Employee Tax Exemption Declaration",
-				{"employee": self.employee, "payroll_period": payroll_period.name, "docstatus": 1},
-				["total_exemption_amount", "income_from_other_sources"])
-			if declaration:
-				total_exemption_amount, other_incomes = declaration
+	def get_total_exemption_amount(self, payroll_period, tax_slab):
+		total_exemption_amount = 0
+		if tax_slab.allow_tax_exemption:
+			if self.deduct_tax_for_unsubmitted_tax_exemption_proof:
+				exemption_proof = frappe.db.get_value("Employee Tax Exemption Proof Submission",
+					{"employee": self.employee, "payroll_period": payroll_period.name, "docstatus": 1},
+					["exemption_amount"])
+				if exemption_proof:
+					total_exemption_amount = exemption_proof
+			else:
+				declaration = frappe.db.get_value("Employee Tax Exemption Declaration",
+					{"employee": self.employee, "payroll_period": payroll_period.name, "docstatus": 1},
+					["total_exemption_amount"])
+				if declaration:
+					total_exemption_amount = declaration
 
-		return total_exemption_amount, other_incomes
+			total_exemption_amount += flt(tax_slab.standard_tax_exemption_amount)
 
-	def calculate_tax_by_tax_slab(self, payroll_period, annual_taxable_earning):
-		payroll_period_obj = frappe.get_doc("Payroll Period", payroll_period)
-		annual_taxable_earning -= flt(payroll_period_obj.standard_tax_exemption_amount)
+		return total_exemption_amount
+
+	def get_income_form_other_sources(self, payroll_period):
+		return frappe.get_all("Employee Other Income",
+			filters={
+				"employee": self.employee,
+				"payroll_period": payroll_period.name,
+				"company": self.company,
+				"docstatus": 1
+			},
+			fields="SUM(amount) as total_amount"
+		)[0].total_amount
+
+	def calculate_tax_by_tax_slab(self, annual_taxable_earning, tax_slab):
 		data = self.get_data_for_eval()
 		data.update({"annual_taxable_earning": annual_taxable_earning})
-		taxable_amount = 0
-		for slab in payroll_period_obj.taxable_salary_slabs:
+		tax_amount = 0
+		for slab in tax_slab.slabs:
 			if slab.condition and not self.eval_tax_slab_condition(slab.condition, data):
 				continue
-			if not slab.to_amount and annual_taxable_earning > slab.from_amount:
-				taxable_amount += (annual_taxable_earning - slab.from_amount) * slab.percent_deduction *.01
+			if not slab.to_amount and annual_taxable_earning >= slab.from_amount:
+				tax_amount += (annual_taxable_earning - slab.from_amount + 1) * slab.percent_deduction *.01
 				continue
-			if annual_taxable_earning > slab.from_amount and annual_taxable_earning < slab.to_amount:
-				taxable_amount += (annual_taxable_earning - slab.from_amount) * slab.percent_deduction *.01
-			elif annual_taxable_earning > slab.from_amount and annual_taxable_earning > slab.to_amount:
-				taxable_amount += (slab.to_amount - slab.from_amount) * slab.percent_deduction * .01
-		return taxable_amount
+			if annual_taxable_earning >= slab.from_amount and annual_taxable_earning < slab.to_amount:
+				tax_amount += (annual_taxable_earning - slab.from_amount + 1) * slab.percent_deduction *.01
+			elif annual_taxable_earning >= slab.from_amount and annual_taxable_earning >= slab.to_amount:
+				tax_amount += (slab.to_amount - slab.from_amount + 1) * slab.percent_deduction * .01
+
+		# other taxes and charges on income tax
+		for d in tax_slab.other_taxes_and_charges:
+			if flt(d.min_taxable_income) and flt(d.min_taxable_income) > tax_amount:
+				continue
+
+			if flt(d.max_taxable_income) and flt(d.max_taxable_income) < tax_amount:
+				continue
+			
+			tax_amount += tax_amount * flt(d.percent) / 100
+
+		return tax_amount
 
 	def eval_tax_slab_condition(self, condition, data):
 		try:
@@ -869,7 +1008,7 @@
 		if not self.salary_slip_based_on_timesheet:
 			self.get_date_details()
 		self.pull_emp_details()
-		self.get_leave_details(for_preview=for_preview)
+		self.get_working_days_details(for_preview=for_preview)
 		self.calculate_net_pay()
 
 	def pull_emp_details(self):
@@ -878,8 +1017,8 @@
 			self.bank_name = emp.bank_name
 			self.bank_account_no = emp.bank_ac_no
 
-	def process_salary_based_on_leave(self, lwp=0):
-		self.get_leave_details(lwp=lwp)
+	def process_salary_based_on_working_days(self):
+		self.get_working_days_details(lwp=self.leave_without_pay)
 		self.calculate_net_pay()
 
 def unlink_ref_doc_from_salary_slip(ref_no):
diff --git a/erpnext/hr/doctype/salary_slip/test_salary_slip.py b/erpnext/hr/doctype/salary_slip/test_salary_slip.py
index ecccac7..fc687a3 100644
--- a/erpnext/hr/doctype/salary_slip/test_salary_slip.py
+++ b/erpnext/hr/doctype/salary_slip/test_salary_slip.py
@@ -21,18 +21,105 @@
 		make_earning_salary_component(setup=True, company_list=["_Test Company"])
 		make_deduction_salary_component(setup=True, company_list=["_Test Company"])
 
-		for dt in ["Leave Application", "Leave Allocation", "Salary Slip"]:
+		for dt in ["Leave Application", "Leave Allocation", "Salary Slip", "Attendance"]:
 			frappe.db.sql("delete from `tab%s`" % dt)
 
 		self.make_holiday_list()
 
 		frappe.db.set_value("Company", erpnext.get_default_company(), "default_holiday_list", "Salary Slip Test Holiday List")
 		frappe.db.set_value("HR Settings", None, "email_salary_slip_to_employee", 0)
-
+		frappe.db.set_value('HR Settings', None, 'leave_status_notification_template', None)
+		frappe.db.set_value('HR Settings', None, 'leave_approval_notification_template', None)
+		
 	def tearDown(self):
 		frappe.db.set_value("HR Settings", None, "include_holidays_in_total_working_days", 0)
 		frappe.set_user("Administrator")
 
+	def test_payment_days_based_on_attendance(self):
+		from erpnext.hr.doctype.attendance.attendance import mark_attendance
+		no_of_days = self.get_no_of_days()
+
+		# Payroll based on attendance
+		frappe.db.set_value("HR Settings", None, "payroll_based_on", "Attendance")
+		frappe.db.set_value("HR Settings", None, "daily_wages_fraction_for_half_day", 0.75)
+
+		emp_id = make_employee("test_for_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)
+
+		month_start_date = get_first_day(nowdate())
+		month_end_date = get_last_day(nowdate())
+
+		first_sunday = frappe.db.sql("""
+			select holiday_date from `tabHoliday`
+			where parent = 'Salary Slip Test Holiday List'
+				and holiday_date between %s and %s
+			order by holiday_date
+		""", (month_start_date, month_end_date))[0][0]
+
+		mark_attendance(emp_id, first_sunday, 'Absent', ignore_validate=True) # invalid lwp
+		mark_attendance(emp_id, add_days(first_sunday, 1), 'Absent', ignore_validate=True) # valid lwp
+		mark_attendance(emp_id, add_days(first_sunday, 2), 'Half Day', leave_type='Leave Without Pay', ignore_validate=True) # valid 0.75 lwp
+		mark_attendance(emp_id, add_days(first_sunday, 3), 'On Leave', leave_type='Leave Without Pay', ignore_validate=True) # valid lwp
+		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")
+
+		self.assertEqual(ss.leave_without_pay, 2.25)
+
+		days_in_month = no_of_days[0]
+		no_of_holidays = no_of_days[1]
+
+		self.assertEqual(ss.payment_days, days_in_month - no_of_holidays - 2.25)
+
+		#Gross pay calculation based on attendances
+		gross_pay = 78000 - ((78000 / (days_in_month - no_of_holidays)) * flt(ss.leave_without_pay))
+
+		self.assertEqual(ss.gross_pay, gross_pay)
+
+		frappe.db.set_value("HR Settings", None, "payroll_based_on", "Leave")
+
+	def test_payment_days_based_on_leave_application(self):
+		no_of_days = self.get_no_of_days()
+
+		# Payroll based on attendance
+		frappe.db.set_value("HR Settings", None, "payroll_based_on", "Leave")
+
+		emp_id = make_employee("test_for_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)
+
+		month_start_date = get_first_day(nowdate())
+		month_end_date = get_last_day(nowdate())
+
+		first_sunday = frappe.db.sql("""
+			select holiday_date from `tabHoliday`
+			where parent = 'Salary Slip Test Holiday List'
+				and holiday_date between %s and %s
+			order by holiday_date
+		""", (month_start_date, month_end_date))[0][0]
+
+		make_leave_application(emp_id, first_sunday, add_days(first_sunday, 3), "Leave Without Pay")
+
+		ss = make_employee_salary_slip("test_for_attendance@salary.com", "Monthly")
+
+		self.assertEqual(ss.leave_without_pay, 3)
+
+		days_in_month = no_of_days[0]
+		no_of_holidays = no_of_days[1]
+
+		self.assertEqual(ss.payment_days, days_in_month - no_of_holidays - 3)
+
+		#Gross pay calculation based on attendances
+		gross_pay = 78000 - ((78000 / (days_in_month - no_of_holidays)) * flt(ss.leave_without_pay))
+
+		self.assertEqual(ss.gross_pay, gross_pay)
+
+		frappe.db.set_value("HR 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("HR Settings", None, "include_holidays_in_total_working_days", 1)
@@ -47,10 +134,7 @@
 		self.assertEqual(ss.payment_days, no_of_days[0])
 		self.assertEqual(ss.earnings[0].amount, 50000)
 		self.assertEqual(ss.earnings[1].amount, 3000)
-		self.assertEqual(ss.deductions[0].amount, 5000)
-		self.assertEqual(ss.deductions[1].amount, 5000)
 		self.assertEqual(ss.gross_pay, 78000)
-		self.assertEqual(ss.net_pay, 68000.0)
 
 	def test_salary_slip_with_holidays_excluded(self):
 		no_of_days = self.get_no_of_days()
@@ -67,10 +151,7 @@
 		self.assertEqual(ss.earnings[0].amount, 50000)
 		self.assertEqual(ss.earnings[0].default_amount, 50000)
 		self.assertEqual(ss.earnings[1].amount, 3000)
-		self.assertEqual(ss.deductions[0].amount, 5000)
-		self.assertEqual(ss.deductions[1].amount, 5000)
 		self.assertEqual(ss.gross_pay, 78000)
-		self.assertEqual(ss.net_pay, 68000.0)
 
 	def test_payment_days(self):
 		no_of_days = self.get_no_of_days()
@@ -80,8 +161,8 @@
 		# set joinng date in the same month
 		make_employee("test_employee@salary.com")
 		if getdate(nowdate()).day >= 15:
-			date_of_joining = getdate(add_days(nowdate(),-10))
 			relieving_date = getdate(add_days(nowdate(),-10))
+			date_of_joining = getdate(add_days(nowdate(),-10))
 		elif getdate(nowdate()).day < 15 and getdate(nowdate()).day >= 5:
 			date_of_joining = getdate(add_days(nowdate(),-3))
 			relieving_date = getdate(add_days(nowdate(),-3))
@@ -131,9 +212,7 @@
 	def test_email_salary_slip(self):
 		frappe.db.sql("delete from `tabEmail Queue`")
 
-		hr_settings = frappe.get_doc("HR Settings", "HR Settings")
-		hr_settings.email_salary_slip_to_employee = 1
-		hr_settings.save()
+		frappe.db.set_value("HR Settings", None, "email_salary_slip_to_employee", 1)
 
 		make_employee("test_employee@salary.com")
 		ss = make_employee_salary_slip("test_employee@salary.com", "Monthly")
@@ -203,8 +282,11 @@
 		# as per assigned salary structure 40500 in monthly salary so 236000*5/100/12
 		frappe.db.sql("""delete from `tabPayroll Period`""")
 		frappe.db.sql("""delete from `tabSalary Component`""")
+	
 		payroll_period = create_payroll_period()
-		create_tax_slab(payroll_period)
+
+		create_tax_slab(payroll_period, allow_tax_exemption=True)
+
 		employee = make_employee("test_tax@salary.slip")
 		delete_docs = [
 			"Salary Slip",
@@ -230,8 +312,7 @@
 			payroll_period, deduct_random=False)
 		tax_paid = get_tax_paid_in_period(employee)
 
-		# total taxable income 586000, 250000 @ 5%, 86000 @ 20% ie. 12500 + 17200
-		annual_tax = 113568
+		annual_tax = 113589.0
 		try:
 			self.assertEqual(tax_paid, annual_tax)
 		except AssertionError:
@@ -255,8 +336,7 @@
 			raise
 
 		# Submit proof for total 120000
-		data["proof-1"] = create_proof_submission(employee, payroll_period, 50000)
-		data["proof-2"] = create_proof_submission(employee, payroll_period, 70000)
+		data["proof"] = create_proof_submission(employee, payroll_period, 120000)
 
 		# Submit benefit claim for total 50000
 		data["benefit-1"] = create_benefit_claim(employee, payroll_period, 15000, "Medical Allowance")
@@ -270,7 +350,7 @@
 
 		# total taxable income 416000, 166000 @ 5% ie. 8300
 		try:
-			self.assertEqual(tax_paid, 88608)
+			self.assertEqual(tax_paid, 82389.0)
 		except AssertionError:
 			print("\nSalary Slip - Tax calculation failed on following case\n", data, "\n")
 			raise
@@ -285,7 +365,7 @@
 		# total taxable income 566000, 250000 @ 5%, 66000 @ 20%, 12500 + 13200
 		tax_paid = get_tax_paid_in_period(employee)
 		try:
-			self.assertEqual(tax_paid, 121211)
+			self.assertEqual(tax_paid, annual_tax)
 		except AssertionError:
 			print("\nSalary Slip - Tax calculation failed on following case\n", data, "\n")
 			raise
@@ -322,11 +402,11 @@
 
 		return [no_of_days_in_month[1], no_of_holidays_in_month]
 
-
 def make_employee_salary_slip(user, payroll_frequency, salary_structure=None):
 	from erpnext.hr.doctype.salary_structure.test_salary_structure import make_salary_structure
 	if not salary_structure:
 		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})})
@@ -456,17 +536,15 @@
 		{
 			"salary_component": 'Professional Tax',
 			"abbr":'PT',
-			"condition": 'base > 10000',
-			"formula": 'base*.1',
 			"type": "Deduction",
-			"amount_based_on_formula": 1
+			"amount": 200,
+			"exempted_from_income_tax": 1
+
 		},
 		{
 			"salary_component": 'TDS',
 			"abbr":'T',
-			"formula": 'base*.1',
 			"type": "Deduction",
-			"amount_based_on_formula": 1,
 			"depends_on_payment_days": 0,
 			"variable_based_on_taxable_salary": 1,
 			"round_to_the_nearest_integer": 1
@@ -477,9 +555,7 @@
 			"salary_component": 'TDS',
 			"abbr":'T',
 			"condition": 'employment_type=="Intern"',
-			"formula": 'base*.1',
 			"type": "Deduction",
-			"amount_based_on_formula": 1,
 			"round_to_the_nearest_integer": 1
 		})
 	if setup or test_tax:
@@ -535,29 +611,47 @@
 	}).submit()
 	return claim_date
 
-def create_tax_slab(payroll_period):
-	data = [
+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
+
+	slabs = [
 		{
 			"from_amount": 250000,
 			"to_amount": 500000,
-			"percent_deduction": 5.2,
+			"percent_deduction": 5,
 			"condition": "annual_taxable_earning > 500000"
 		},
 		{
 			"from_amount": 500001,
 			"to_amount": 1000000,
-			"percent_deduction": 20.8
+			"percent_deduction": 20
 		},
 		{
 			"from_amount": 1000001,
-			"percent_deduction": 31.2
+			"percent_deduction": 30
 		}
 	]
-	payroll_period.taxable_salary_slabs = []
-	for item in data:
-		payroll_period.append("taxable_salary_slabs", item)
-	payroll_period.standard_tax_exemption_amount = 52500
-	payroll_period.save()
+
+	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)
+
+	if allow_tax_exemption:
+		income_tax_slab.allow_tax_exemption = 1
+		income_tax_slab.standard_tax_exemption_amount = 50000
+
+	for item in slabs:
+		income_tax_slab.append("slabs", item)
+
+	income_tax_slab.append("other_taxes_and_charges", {
+		"description": "cess",
+		"percent": 4
+	})
+
+	income_tax_slab.save()
+	if not dont_submit:
+		income_tax_slab.submit()
 
 def create_salary_slips_for_payroll_period(employee, salary_structure, payroll_period, deduct_random=True):
 	deducted_dates = []
@@ -595,3 +689,17 @@
 		"type": "Earning"
 	}).submit()
 	return salary_date
+
+def make_leave_application(employee, from_date, to_date, leave_type, company=None):
+	leave_application = frappe.get_doc(dict(
+		doctype = 'Leave Application',
+		employee = employee,
+		leave_type = leave_type,
+		from_date = from_date,
+		to_date = to_date,
+		company = company or erpnext.get_default_company() or "_Test Company",
+		docstatus = 1,
+		status = "Approved",
+		leave_approver = 'test@example.com'
+	))
+	leave_application.submit()
\ No newline at end of file
diff --git a/erpnext/hr/doctype/salary_structure/salary_structure.js b/erpnext/hr/doctype/salary_structure/salary_structure.js
index 7120448..7748403 100755
--- a/erpnext/hr/doctype/salary_structure/salary_structure.js
+++ b/erpnext/hr/doctype/salary_structure/salary_structure.js
@@ -82,6 +82,7 @@
                 {fieldname:"employee", fieldtype: "Link", options: "Employee", label: __("Employee")},
 				{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'},
 				{fieldname:'base_col_br', fieldtype:'Column Break'},
 				{fieldname:'base', fieldtype:'Currency', label: __('Base')},
 				{fieldname:'variable', fieldtype:'Currency', label: __('Variable')}
diff --git a/erpnext/hr/doctype/salary_structure/salary_structure.py b/erpnext/hr/doctype/salary_structure/salary_structure.py
index 568277f..5ba7f1c 100644
--- a/erpnext/hr/doctype/salary_structure/salary_structure.py
+++ b/erpnext/hr/doctype/salary_structure/salary_structure.py
@@ -16,6 +16,7 @@
 		self.validate_amount()
 		self.strip_condition_and_formula_fields()
 		self.validate_max_benefits_with_flexi()
+		self.validate_component_based_on_tax_slab()
 
 	def set_missing_values(self):
 		overwritten_fields = ["depends_on_payment_days", "variable_based_on_taxable_salary", "is_tax_applicable", "is_flexible_benefit"]
@@ -34,6 +35,12 @@
 						for fieldname in overwritten_fields_if_missing:
 							d.set(fieldname, component_default_value.get(fieldname))
 
+	def validate_component_based_on_tax_slab(self):
+		for row in self.deductions:
+			if row.variable_based_on_taxable_salary and (row.amount or row.formula):
+				frappe.throw(_("Row #{0}: Cannot set amount or formula for Salary Component {1} with Variable Based On Taxable Salary")
+					.format(row.idx, row.salary_component))
+
 	def validate_amount(self):
 		if flt(self.net_pay) < 0 and self.salary_slip_based_on_timesheet:
 			frappe.throw(_("Net pay cannot be negative"))
@@ -82,21 +89,23 @@
 
 	@frappe.whitelist()
 	def assign_salary_structure(self, company=None, grade=None, department=None, designation=None,employee=None,
-			from_date=None, base=None,variable=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)
 
 		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)
+					employees=employees, salary_structure=self,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)
+				assign_salary_structure_for_employees(employees, self, 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):
+def assign_salary_structure_for_employees(employees, salary_structure, 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
@@ -105,7 +114,8 @@
 			continue
 		count +=1
 
-		salary_structures_assignment = create_salary_structures_assignment(employee, salary_structure, from_date, base, variable)
+		salary_structures_assignment = create_salary_structures_assignment(employee,
+			salary_structure, 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..."))
 
@@ -113,7 +123,7 @@
 		frappe.msgprint(_("Structures have been assigned successfully"))
 
 
-def create_salary_structures_assignment(employee, salary_structure, from_date, base, variable):
+def create_salary_structures_assignment(employee, salary_structure, from_date, base, variable, income_tax_slab=None):
 	assignment = frappe.new_doc("Salary Structure Assignment")
 	assignment.employee = employee
 	assignment.salary_structure = salary_structure.name
@@ -121,6 +131,7 @@
 	assignment.from_date = from_date
 	assignment.base = base
 	assignment.variable = variable
+	assignment.income_tax_slab = income_tax_slab
 	assignment.save(ignore_permissions = True)
 	assignment.submit()
 	return assignment.name
@@ -138,7 +149,7 @@
 	return salary_structures_assignments
 
 @frappe.whitelist()
-def make_salary_slip(source_name, target_doc = None, employee = None, as_print = False, print_format = None, for_preview=0):
+def make_salary_slip(source_name, target_doc = None, employee = None, as_print = False, print_format = None, for_preview=0, ignore_permissions=False):
 	def postprocess(source, target):
 		if employee:
 			employee_details = frappe.db.get_value("Employee", employee,
@@ -158,7 +169,7 @@
 				"name": "salary_structure"
 			}
 		}
-	}, target_doc, postprocess, ignore_child_tables=True)
+	}, target_doc, postprocess, ignore_child_tables=True, ignore_permissions=ignore_permissions)
 
 	if cint(as_print):
 		doc.name = 'Preview for {0}'.format(employee)
diff --git a/erpnext/hr/doctype/salary_structure/test_salary_structure.py b/erpnext/hr/doctype/salary_structure/test_salary_structure.py
index 6ca6dfd..c1869f0 100644
--- a/erpnext/hr/doctype/salary_structure/test_salary_structure.py
+++ b/erpnext/hr/doctype/salary_structure/test_salary_structure.py
@@ -9,8 +9,9 @@
 from frappe.utils import nowdate, add_days, add_years, getdate, add_months
 from erpnext.hr.doctype.salary_structure.salary_structure import make_salary_slip
 from erpnext.hr.doctype.salary_slip.test_salary_slip import make_earning_salary_component,\
-	make_deduction_salary_component, make_employee_salary_slip
+	make_deduction_salary_component, make_employee_salary_slip, create_tax_slab
 from erpnext.hr.doctype.employee.test_employee import make_employee
+from erpnext.hr.doctype.employee_tax_exemption_declaration.test_employee_tax_exemption_declaration import create_payroll_period
 
 
 test_dependencies = ["Fiscal Year"]
@@ -70,10 +71,8 @@
 			self.assertEqual(sal_slip.get("earnings")[1].amount, 3000)
 			self.assertEqual(sal_slip.get("earnings")[2].amount, 25000)
 			self.assertEqual(sal_slip.get("gross_pay"), 78000)
-			self.assertEqual(sal_slip.get("deductions")[0].amount, 5000)
-			self.assertEqual(sal_slip.get("deductions")[1].amount, 5000)
-			self.assertEqual(sal_slip.get("total_deduction"), 10000)
-			self.assertEqual(sal_slip.get("net_pay"), 68000)
+			self.assertEqual(sal_slip.get("deductions")[0].amount, 200)
+			self.assertEqual(sal_slip.get("net_pay"), 78000 - sal_slip.get("total_deduction"))
 
 	def test_whitespaces_in_formula_conditions_fields(self):
 		salary_structure = make_salary_structure("Salary Structure Sample", "Monthly", dont_submit=True)
@@ -112,6 +111,7 @@
 	test_tax=False, company=None):
 	if test_tax:
 		frappe.db.sql("""delete from `tabSalary Structure` where name=%s""",(salary_structure))
+
 	if not frappe.db.exists('Salary Structure', salary_structure):
 		details = {
 			"doctype": "Salary Structure",
@@ -124,7 +124,8 @@
 		}
 		if other_details and isinstance(other_details, dict):
 			details.update(other_details)
-		salary_structure_doc = frappe.get_doc(details).insert()
+		salary_structure_doc = frappe.get_doc(details)
+		salary_structure_doc.insert()
 		if not dont_submit:
 			salary_structure_doc.submit()
 	else:
@@ -139,13 +140,18 @@
 def create_salary_structure_assignment(employee, salary_structure, from_date=None, company=None):
 	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)
+
 	salary_structure_assignment = frappe.new_doc("Salary Structure Assignment")
 	salary_structure_assignment.employee = employee
 	salary_structure_assignment.base = 50000
 	salary_structure_assignment.variable = 5000
-	salary_structure_assignment.from_date = from_date or add_months(nowdate(), -1)
+	salary_structure_assignment.from_date = from_date or add_days(nowdate(), -1)
 	salary_structure_assignment.salary_structure = salary_structure
 	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
diff --git a/erpnext/hr/doctype/salary_structure_assignment/salary_structure_assignment.js b/erpnext/hr/doctype/salary_structure_assignment/salary_structure_assignment.js
index 56a05e0..818e853 100644
--- a/erpnext/hr/doctype/salary_structure_assignment/salary_structure_assignment.js
+++ b/erpnext/hr/doctype/salary_structure_assignment/salary_structure_assignment.js
@@ -20,6 +20,16 @@
 				}
 			}
 		});
+
+		frm.set_query("income_tax_slab", function() {
+			return {
+				filters: {
+					company: frm.doc.company,
+					docstatus: 1,
+					disabled: 0
+				}
+			}
+		});
 	},
 	employee: function(frm) {
 		if(frm.doc.employee){
diff --git a/erpnext/hr/doctype/salary_structure_assignment/salary_structure_assignment.json b/erpnext/hr/doctype/salary_structure_assignment/salary_structure_assignment.json
index 380c889..0098aa8 100644
--- a/erpnext/hr/doctype/salary_structure_assignment/salary_structure_assignment.json
+++ b/erpnext/hr/doctype/salary_structure_assignment/salary_structure_assignment.json
@@ -10,11 +10,12 @@
   "employee",
   "employee_name",
   "department",
-  "designation",
+  "company",
   "column_break_6",
+  "designation",
   "salary_structure",
   "from_date",
-  "company",
+  "income_tax_slab",
   "section_break_7",
   "base",
   "column_break_9",
@@ -113,11 +114,17 @@
    "options": "Salary Structure Assignment",
    "print_hide": 1,
    "read_only": 1
+  },
+  {
+   "fieldname": "income_tax_slab",
+   "fieldtype": "Link",
+   "label": "Income Tax Slab",
+   "options": "Income Tax Slab"
   }
  ],
  "is_submittable": 1,
  "links": [],
- "modified": "2019-12-31 16:35:34.415099",
+ "modified": "2020-04-25 18:24:23.617088",
  "modified_by": "Administrator",
  "module": "HR",
  "name": "Salary Structure Assignment",
diff --git a/erpnext/hr/doctype/upload_attendance/upload_attendance.py b/erpnext/hr/doctype/upload_attendance/upload_attendance.py
index 1707e35..f75bb41 100644
--- a/erpnext/hr/doctype/upload_attendance/upload_attendance.py
+++ b/erpnext/hr/doctype/upload_attendance/upload_attendance.py
@@ -9,6 +9,8 @@
 from frappe import _
 from frappe.utils.csvutils import UnicodeWriter
 from frappe.model.document import Document
+from erpnext.hr.doctype.employee.employee import get_holiday_list_for_employee
+from erpnext.hr.utils import get_holidays_for_employee
 
 class UploadAttendance(Document):
 	pass
@@ -48,6 +50,7 @@
 def get_data(args):
 	dates = get_dates(args)
 	employees = get_active_employees()
+	holidays = get_holidays_for_employees([employee.name for employee in employees], args["from_date"], args["to_date"])
 	existing_attendance_records = get_existing_attendance_records(args)
 	data = []
 	for date in dates:
@@ -63,6 +66,9 @@
 				and getdate(employee.date_of_joining) <= getdate(date) \
 				and getdate(employee.relieving_date) >= getdate(date):
 					existing_attendance = existing_attendance_records[tuple([getdate(date), employee.name])]
+
+			employee_holiday_list = get_holiday_list_for_employee(employee.name)
+
 			row = [
 				existing_attendance and existing_attendance.name or "",
 				employee.name, employee.employee_name, date,
@@ -70,9 +76,22 @@
 				existing_attendance and existing_attendance.leave_type or "", employee.company,
 				existing_attendance and existing_attendance.naming_series or get_naming_series(),
 			]
+			if date in holidays[employee_holiday_list]:
+				row[4] =  "Holiday"
 			data.append(row)
+
 	return data
 
+def get_holidays_for_employees(employees, from_date, to_date):
+	holidays = {}
+	for employee in employees:
+		holiday_list = get_holiday_list_for_employee(employee)
+		holiday = get_holidays_for_employee(employee, getdate(from_date), getdate(to_date))
+		if holiday_list not in holidays:
+			holidays[holiday_list] = holiday
+
+	return holidays
+
 def writedata(w, data):
 	for row in data:
 		w.writerow(row)
@@ -123,6 +142,11 @@
 	frappe.enqueue(import_attendances, rows=rows, now=True if len(rows) < 200 else False)
 
 def import_attendances(rows):
+
+	def remove_holidays(rows):
+		rows = [ row for row in rows if row[4] != "Holiday"]
+		return
+
 	from frappe.modules import scrub
 
 	rows = list(filter(lambda x: x and any(x), rows))
@@ -133,6 +157,8 @@
 	ret = []
 	error = False
 
+	rows = remove_holidays(rows)
+
 	from frappe.utils.csvutils import check_record, import_doc
 
 	for i, row in enumerate(rows):
diff --git a/erpnext/hr/report/employee_leave_balance/employee_leave_balance.py b/erpnext/hr/report/employee_leave_balance/employee_leave_balance.py
index 35c8630..97be5cd 100644
--- a/erpnext/hr/report/employee_leave_balance/employee_leave_balance.py
+++ b/erpnext/hr/report/employee_leave_balance/employee_leave_balance.py
@@ -1,85 +1,186 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
+# Copyright (c) 2013, 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 erpnext.hr.doctype.leave_application.leave_application \
-	import get_leave_balance_on, get_leaves_for_period
-
-from erpnext.hr.report.employee_leave_balance_summary.employee_leave_balance_summary \
-	import get_department_leave_approver_map
+from frappe import _
+from erpnext.hr.doctype.leave_application.leave_application import get_leaves_for_period, get_leave_balance_on, get_leave_allocation_records
 
 def execute(filters=None):
-	leave_types = frappe.db.sql_list("select name from `tabLeave Type` order by name asc")
+	if filters.to_date <= filters.from_date:
+		frappe.throw(_('From date can not be greater than than To date'))
 
-	columns = get_columns(leave_types)
-	data = get_data(filters, leave_types)
+	columns = get_columns()
+	data = get_data(filters)
 
 	return columns, data
 
-def get_columns(leave_types):
-	columns = [
-		_("Employee") + ":Link.Employee:150",
-		_("Employee Name") + "::200",
-		_("Department") +"::150"
-	]
-
-	for leave_type in leave_types:
-		columns.append(_(leave_type) + " " + _("Opening") + ":Float:160")
-		columns.append(_(leave_type) + " " + _("Taken") + ":Float:160")
-		columns.append(_(leave_type) + " " + _("Balance") + ":Float:160")
+def get_columns():
+	columns = [{
+		'label': _('Leave Type'),
+		'fieldtype': 'Link',
+		'fieldname': 'leave_type',
+		'width': 200,
+		'options': 'Leave Type'
+	}, {
+		'label': _('Employee'),
+		'fieldtype': 'Link',
+		'fieldname': 'employee',
+		'width': 100,
+		'options': 'Employee'
+	}, {
+		'label': _('Employee Name'),
+		'fieldtype': 'Data',
+		'fieldname': 'employee_name',
+		'width': 100,
+	}, {
+		'label': _('Opening Balance'),
+		'fieldtype': 'float',
+		'fieldname': 'opening_balance',
+		'width': 130,
+	}, {
+		'label': _('Leaves Allocated'),
+		'fieldtype': 'float',
+		'fieldname': 'leaves_allocated',
+		'width': 130,
+	}, {
+		'label': _('Leaves Taken'),
+		'fieldtype': 'float',
+		'fieldname': 'leaves_taken',
+		'width': 130,
+	}, {
+		'label': _('Leaves Expired'),
+		'fieldtype': 'float',
+		'fieldname': 'leaves_expired',
+		'width': 130,
+	}, {
+		'label': _('Closing Balance'),
+		'fieldtype': 'float',
+		'fieldname': 'closing_balance',
+		'width': 130,
+	}]
 
 	return columns
 
-def get_conditions(filters):
-	conditions = {
-		"status": "Active",
-		"company": filters.company,
-	}
-	if filters.get("department"):
-		conditions.update({"department": filters.get("department")})
-	if filters.get("employee"):
-		conditions.update({"employee": filters.get("employee")})
+def get_data(filters):
+	leave_types = frappe.db.sql_list("SELECT `name` FROM `tabLeave Type` ORDER BY `name` ASC")
 
-	return conditions
-
-def get_data(filters, leave_types):
-	user = frappe.session.user
 	conditions = get_conditions(filters)
 
-	if filters.to_date <= filters.from_date:
-		frappe.throw(_("From date can not be greater than than To date"))
-
-	active_employees = frappe.get_all("Employee",
-		filters=conditions,
-		fields=["name", "employee_name", "department", "user_id", "leave_approver"])
-
+	user = frappe.session.user
 	department_approver_map = get_department_leave_approver_map(filters.get('department'))
 
+	active_employees = frappe.get_list('Employee',
+		filters=conditions,
+		fields=['name', 'employee_name', 'department', 'user_id', 'leave_approver'])
+
 	data = []
-	for employee in active_employees:
-		leave_approvers = department_approver_map.get(employee.department_name, [])
-		if employee.leave_approver:
-			leave_approvers.append(employee.leave_approver)
 
-		if (len(leave_approvers) and user in leave_approvers) or (user in ["Administrator", employee.user_id]) or ("HR Manager" in frappe.get_roles(user)):
-			row = [employee.name, employee.employee_name, employee.department]
+	for leave_type in leave_types:
+		if len(active_employees) > 1:
+			data.append({
+				'leave_type': leave_type
+			})
+		else:
+			row = frappe._dict({
+				'leave_type': leave_type
+			})
 
-			for leave_type in leave_types:
-				# leaves taken
+		for employee in active_employees:
+
+			leave_approvers = department_approver_map.get(employee.department_name, []).append(employee.leave_approver)
+
+			if (leave_approvers and len(leave_approvers) and user in leave_approvers) or (user in ["Administrator", employee.user_id]) \
+				or ("HR Manager" in frappe.get_roles(user)):
+				if len(active_employees) > 1:
+					row = frappe._dict()
+				row.employee = employee.name,
+				row.employee_name = employee.employee_name
+
 				leaves_taken = get_leaves_for_period(employee.name, leave_type,
 					filters.from_date, filters.to_date) * -1
 
-				# opening balance
+				new_allocation, expired_leaves = get_allocated_and_expired_leaves(filters.from_date, filters.to_date, employee.name, leave_type)
+
+
 				opening = get_leave_balance_on(employee.name, leave_type, filters.from_date)
+				closing = get_leave_balance_on(employee.name, leave_type, filters.to_date)
 
-				# closing balance
-				closing = max(opening - leaves_taken, 0)
+				row.leaves_allocated = new_allocation
+				row.leaves_expired = expired_leaves - leaves_taken if expired_leaves - leaves_taken > 0 else 0
+				row.opening_balance = opening
+				row.leaves_taken = leaves_taken
+				row.closing_balance = closing
+				row.indent = 1
+				data.append(row)
+				new_leaves_allocated = 0
 
-				row += [opening, leaves_taken, closing]
 
-			data.append(row)
+	return data
 
-	return data
\ No newline at end of file
+def get_conditions(filters):
+	conditions={
+		'status': 'Active',
+	}
+	if filters.get('employee'):
+		conditions['name'] = filters.get('employee')
+
+	if filters.get('employee'):
+		conditions['name'] = filters.get('employee')
+
+	return conditions
+
+def get_department_leave_approver_map(department=None):
+	conditions=''
+	if department:
+		conditions="and (department_name = '%(department)s' or parent_department = '%(department)s')"%{'department': department}
+
+	# get current department and all its child
+	department_list = frappe.db.sql_list(""" SELECT name FROM `tabDepartment` WHERE disabled=0 {0}""".format(conditions)) #nosec
+
+	# retrieve approvers list from current department and from its subsequent child departments
+	approver_list = frappe.get_all('Department Approver', filters={
+		'parentfield': 'leave_approvers',
+		'parent': ('in', department_list)
+	}, fields=['parent', 'approver'], as_list=1)
+
+	approvers = {}
+
+	for k, v in approver_list:
+		approvers.setdefault(k, []).append(v)
+
+	return approvers
+
+def get_allocated_and_expired_leaves(from_date, to_date, employee, leave_type):
+
+	from frappe.utils import getdate
+
+	new_allocation = 0
+	expired_leaves = 0
+
+	records= frappe.db.sql("""
+		SELECT
+			employee, leave_type, from_date, to_date, leaves, transaction_name,
+			is_carry_forward, is_expired
+		FROM `tabLeave Ledger Entry`
+		WHERE employee=%(employee)s AND leave_type=%(leave_type)s
+			AND docstatus=1 AND leaves>0
+			AND (from_date between %(from_date)s AND %(to_date)s
+				OR to_date between %(from_date)s AND %(to_date)s
+				OR (from_date < %(from_date)s AND to_date > %(to_date)s))
+	""", {
+		"from_date": from_date,
+		"to_date": to_date,
+		"employee": employee,
+		"leave_type": leave_type
+	}, as_dict=1)
+
+	for record in records:
+		if record.to_date <= getdate(to_date):
+			expired_leaves += record.leaves
+
+		if record.from_date >= getdate(from_date):
+			new_allocation += record.leaves
+
+	return new_allocation, expired_leaves
diff --git a/erpnext/hr/report/employee_leave_balance_summary/employee_leave_balance_summary.js b/erpnext/hr/report/employee_leave_balance_summary/employee_leave_balance_summary.js
index 3fb8f6e..cb05d11 100644
--- a/erpnext/hr/report/employee_leave_balance_summary/employee_leave_balance_summary.js
+++ b/erpnext/hr/report/employee_leave_balance_summary/employee_leave_balance_summary.js
@@ -5,18 +5,11 @@
 frappe.query_reports['Employee Leave Balance Summary'] = {
 	filters: [
 		{
-			fieldname:'from_date',
-			label: __('From Date'),
+			fieldname:'date',
+			label: __('Date'),
 			fieldtype: 'Date',
 			reqd: 1,
-			default: frappe.defaults.get_default('year_start_date')
-		},
-		{
-			fieldname:'to_date',
-			label: __('To Date'),
-			fieldtype: 'Date',
-			reqd: 1,
-			default: frappe.defaults.get_default('year_end_date')
+			default: frappe.datetime.now_date()
 		},
 		{
 			fieldname:'company',
diff --git a/erpnext/hr/report/employee_leave_balance_summary/employee_leave_balance_summary.py b/erpnext/hr/report/employee_leave_balance_summary/employee_leave_balance_summary.py
index 777de02..a5cdecf 100644
--- a/erpnext/hr/report/employee_leave_balance_summary/employee_leave_balance_summary.py
+++ b/erpnext/hr/report/employee_leave_balance_summary/employee_leave_balance_summary.py
@@ -1,130 +1,75 @@
-# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors
-# For license information, please see license.txt
+# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
+# License: GNU General Public License v3. See license.txt
 
 from __future__ import unicode_literals
 import frappe
-from frappe.utils import flt
 from frappe import _
-from erpnext.hr.doctype.leave_application.leave_application import get_leaves_for_period, get_leave_balance_on
+from frappe.utils import flt
+from erpnext.hr.doctype.leave_application.leave_application \
+	import get_leave_balance_on, get_leaves_for_period
+
+from erpnext.hr.report.employee_leave_balance.employee_leave_balance \
+	import get_department_leave_approver_map
 
 def execute(filters=None):
-	if filters.to_date <= filters.from_date:
-		frappe.throw(_('From date can not be greater than than To date'))
+	leave_types = frappe.db.sql_list("select name from `tabLeave Type` order by name asc")
 
-	columns = get_columns()
-	data = get_data(filters)
+	columns = get_columns(leave_types)
+	data = get_data(filters, leave_types)
 
 	return columns, data
 
-def get_columns():
-	columns = [{
-		'label': _('Leave Type'),
-		'fieldtype': 'Link',
-		'fieldname': 'leave_type',
-		'width': 300,
-		'options': 'Leave Type'
-	}, {
-		'label': _('Employee'),
-		'fieldtype': 'Link',
-		'fieldname': 'employee',
-		'width': 100,
-		'options': 'Employee'
-	}, {
-		'label': _('Employee Name'),
-		'fieldtype': 'Data',
-		'fieldname': 'employee_name',
-		'width': 100,
-	}, {
-		'label': _('Opening Balance'),
-		'fieldtype': 'float',
-		'fieldname': 'opening_balance',
-		'width': 160,
-	}, {
-		'label': _('Leaves Taken'),
-		'fieldtype': 'float',
-		'fieldname': 'leaves_taken',
-		'width': 160,
-	}, {
-		'label': _('Closing Balance'),
-		'fieldtype': 'float',
-		'fieldname': 'closing_balance',
-		'width': 160,
-	}]
+def get_columns(leave_types):
+	columns = [
+		_("Employee") + ":Link.Employee:150",
+		_("Employee Name") + "::200",
+		_("Department") +"::150"
+	]
+
+	for leave_type in leave_types:
+		columns.append(_(leave_type) + ":Float:160")
 
 	return columns
 
-def get_data(filters):
-	leave_types = frappe.db.sql_list("SELECT `name` FROM `tabLeave Type` ORDER BY `name` ASC")
-
-	conditions = get_conditions(filters)
-
-	user = frappe.session.user
-	department_approver_map = get_department_leave_approver_map(filters.get('department'))
-
-	active_employees = frappe.get_list('Employee',
-		filters=conditions,
-		fields=['name', 'employee_name', 'department', 'user_id', 'leave_approver'])
-
-	data = []
-
-	for leave_type in leave_types:
-		data.append({
-			'leave_type': leave_type
-		})
-		for employee in active_employees:
-			
-			leave_approvers = department_approver_map.get(employee.department_name, []).append(employee.leave_approver)
-
-			if (leave_approvers and len(leave_approvers) and user in leave_approvers) or (user in ["Administrator", employee.user_id]) \
-				or ("HR Manager" in frappe.get_roles(user)):
-				row = frappe._dict({
-					'employee': employee.name,
-					'employee_name': employee.employee_name
-				})
-
-				leaves_taken = get_leaves_for_period(employee.name, leave_type,
-					filters.from_date, filters.to_date) * -1
-
-				opening = get_leave_balance_on(employee.name, leave_type, filters.from_date)
-				closing = get_leave_balance_on(employee.name, leave_type, filters.to_date)
-
-				row.opening_balance = opening
-				row.leaves_taken = leaves_taken
-				row.closing_balance = closing
-				row.indent = 1
-				data.append(row)
-
-	return data
-
 def get_conditions(filters):
-	conditions={
-		'status': 'Active',
+	conditions = {
+		"status": "Active",
+		"company": filters.company,
 	}
-	if filters.get('employee'):
-		conditions['name'] = filters.get('employee')
-
-	if filters.get('employee'):
-		conditions['name'] = filters.get('employee')
+	if filters.get("department"):
+		conditions.update({"department": filters.get("department")})
+	if filters.get("employee"):
+		conditions.update({"employee": filters.get("employee")})
 
 	return conditions
 
-def get_department_leave_approver_map(department=None):
-	conditions=''
-	if department:
-		conditions="and (department_name = '%(department)s' or parent_department = '%(department)s')"%{'department': department}
+def get_data(filters, leave_types):
+	user = frappe.session.user
+	conditions = get_conditions(filters)
 
-	# get current department and all its child
-	department_list = frappe.db.sql_list(""" SELECT name FROM `tabDepartment` WHERE disabled=0 {0}""".format(conditions)) #nosec
+	active_employees = frappe.get_all("Employee",
+		filters=conditions,
+		fields=["name", "employee_name", "department", "user_id", "leave_approver"])
 
-	# retrieve approvers list from current department and from its subsequent child departments
-	approver_list = frappe.get_all('Department Approver', filters={
-		'parentfield': 'leave_approvers',
-		'parent': ('in', department_list)
-	}, fields=['parent', 'approver'], as_list=1)
+	department_approver_map = get_department_leave_approver_map(filters.get('department'))
 
-	approvers = {}
+	data = []
+	for employee in active_employees:
+		leave_approvers = department_approver_map.get(employee.department_name, [])
+		if employee.leave_approver:
+			leave_approvers.append(employee.leave_approver)
 
-	for k, v in approver_list:
-		approvers.setdefault(k, []).append(v)
+		if (len(leave_approvers) and user in leave_approvers) or (user in ["Administrator", employee.user_id]) or ("HR Manager" in frappe.get_roles(user)):
+			row = [employee.name, employee.employee_name, employee.department]
 
-	return approvers
+			for leave_type in leave_types:
+
+				# opening balance
+				opening = get_leave_balance_on(employee.name, leave_type, filters.date)
+
+
+				row += [opening]
+
+			data.append(row)
+
+	return data
\ No newline at end of file
diff --git a/erpnext/hr/report/monthly_attendance_sheet/monthly_attendance_sheet.py b/erpnext/hr/report/monthly_attendance_sheet/monthly_attendance_sheet.py
index b55b45f..9a9e42e 100644
--- a/erpnext/hr/report/monthly_attendance_sheet/monthly_attendance_sheet.py
+++ b/erpnext/hr/report/monthly_attendance_sheet/monthly_attendance_sheet.py
@@ -13,7 +13,7 @@
 	conditions, filters = get_conditions(filters)
 	columns = get_columns(filters)
 	att_map = get_attendance_list(conditions, filters)
-	emp_map = get_employee_details()
+	emp_map = get_employee_details(filters)
 
 	holiday_list = [emp_map[d]["holiday_list"] for d in emp_map if emp_map[d]["holiday_list"]]
 	default_holiday_list = frappe.get_cached_value('Company',  filters.get("company"),  "default_holiday_list")
@@ -140,10 +140,10 @@
 
 	return conditions, filters
 
-def get_employee_details():
+def get_employee_details(filters):
 	emp_map = frappe._dict()
 	for d in frappe.db.sql("""select name, employee_name, designation, department, branch, company,
-		holiday_list from tabEmployee""", as_dict=1):
+		holiday_list from tabEmployee where company = %s""", (filters.get("company")), as_dict=1):
 		emp_map.setdefault(d.name, d)
 
 	return emp_map
diff --git a/erpnext/hr/report/vehicle_expenses/vehicle_expenses.py b/erpnext/hr/report/vehicle_expenses/vehicle_expenses.py
index e5622b7..eab58ff 100644
--- a/erpnext/hr/report/vehicle_expenses/vehicle_expenses.py
+++ b/erpnext/hr/report/vehicle_expenses/vehicle_expenses.py
@@ -12,7 +12,8 @@
 	columns, data, chart = [], [], []
 	if filters.get('fiscal_year'):
 		company = erpnext.get_default_company()
-		period_list = get_period_list(filters.get('fiscal_year'), filters.get('fiscal_year'),"Monthly", company)
+		period_list = get_period_list(filters.get('fiscal_year'), filters.get('fiscal_year'),
+		'', '', 'Fiscal Year', 'Monthly', company=company)
 		columns=get_columns()
 		data=get_log_data(filters)
 		chart=get_chart_data(data,period_list)
diff --git a/erpnext/hr/utils.py b/erpnext/hr/utils.py
index ef27600..cd12510 100644
--- a/erpnext/hr/utils.py
+++ b/erpnext/hr/utils.py
@@ -9,6 +9,8 @@
 from frappe.desk.form import assign_to
 from erpnext.hr.doctype.employee.employee import get_holiday_list_for_employee
 
+class DuplicateDeclarationError(frappe.ValidationError): pass
+
 class EmployeeBoardingController(Document):
 	'''
 		Create the project and the task for the boarding process
@@ -226,6 +228,17 @@
 	else:
 		frappe.throw(_("Please set leave policy for employee {0} in Employee / Grade record").format(employee))
 
+def validate_duplicate_exemption_for_payroll_period(doctype, docname, payroll_period, employee):
+	existing_record = frappe.db.exists(doctype, {
+		"payroll_period": payroll_period,
+		"employee": employee,
+		'docstatus': ['<', 2],
+		'name': ['!=', docname]
+	})
+	if existing_record:
+		frappe.throw(_("{0} already exists for employee {1} and period {2}")
+			.format(doctype, employee, payroll_period), DuplicateDeclarationError)
+
 def validate_tax_declaration(declarations):
 	subcategories = []
 	for d in declarations:
diff --git a/erpnext/loan_management/desk_page/loan_management/loan_management.json b/erpnext/loan_management/desk_page/loan_management/loan_management.json
index 691d2c1..f9ea978 100644
--- a/erpnext/loan_management/desk_page/loan_management/loan_management.json
+++ b/erpnext/loan_management/desk_page/loan_management/loan_management.json
@@ -37,7 +37,7 @@
  "idx": 0,
  "is_standard": 1,
  "label": "Loan Management",
- "modified": "2020-04-01 11:28:51.380509",
+ "modified": "2020-04-02 11:28:51.380509",
  "modified_by": "Administrator",
  "module": "Loan Management",
  "name": "Loan Management",
diff --git a/erpnext/loan_management/doctype/loan/test_loan.py b/erpnext/loan_management/doctype/loan/test_loan.py
index 2d1ad33..90b8534 100644
--- a/erpnext/loan_management/doctype/loan/test_loan.py
+++ b/erpnext/loan_management/doctype/loan/test_loan.py
@@ -236,7 +236,7 @@
 
 		process_loan_interest_accrual_for_term_loans(posting_date=nowdate())
 
-		repayment_entry = create_repayment_entry(loan.name, self.applicant2, add_days(get_last_day(nowdate()), 5),
+		repayment_entry = create_repayment_entry(loan.name, self.applicant2, add_days(nowdate(), 5),
 			"Regular Payment", 89768.75)
 
 		repayment_entry.submit()
diff --git a/erpnext/loan_management/doctype/loan_application/loan_application.js b/erpnext/loan_management/doctype/loan_application/loan_application.js
index aba5f42..6cf47bf 100644
--- a/erpnext/loan_management/doctype/loan_application/loan_application.js
+++ b/erpnext/loan_management/doctype/loan_application/loan_application.js
@@ -31,7 +31,7 @@
 	add_toolbar_buttons: function(frm) {
 		if (frm.doc.status == "Approved") {
 
-			if (frm.doc.is_secured) {
+			if (frm.doc.is_secured_loan) {
 				frappe.db.get_value("Loan Security Pledge", {"loan_application": frm.doc.name, "docstatus": 1}, "name", (r) => {
 					if (!r) {
 						frm.add_custom_button(__('Loan Security Pledge'), function() {
diff --git a/erpnext/loan_management/doctype/loan_disbursement/loan_disbursement.json b/erpnext/loan_management/doctype/loan_disbursement/loan_disbursement.json
index 2d9c45d..c437a98 100644
--- a/erpnext/loan_management/doctype/loan_disbursement/loan_disbursement.json
+++ b/erpnext/loan_management/doctype/loan_disbursement/loan_disbursement.json
@@ -7,17 +7,17 @@
  "engine": "InnoDB",
  "field_order": [
   "against_loan",
-  "disbursement_date",
   "posting_date",
+  "applicant_type",
   "column_break_4",
   "company",
-  "applicant_type",
   "applicant",
   "section_break_7",
+  "disbursement_date",
+  "column_break_8",
   "disbursed_amount",
   "accounting_dimensions_section",
   "cost_center",
-  "section_break_13",
   "customer_details_section",
   "bank_account",
   "amended_from"
@@ -66,6 +66,7 @@
    "read_only": 1
   },
   {
+   "collapsible": 1,
    "fieldname": "accounting_dimensions_section",
    "fieldtype": "Section Break",
    "label": "Accounting Dimensions"
@@ -89,12 +90,8 @@
   },
   {
    "fieldname": "section_break_7",
-   "fieldtype": "Section Break"
-  },
-  {
-   "collapsible": 1,
-   "fieldname": "section_break_13",
-   "fieldtype": "Section Break"
+   "fieldtype": "Section Break",
+   "label": "Disbursement Details"
   },
   {
    "fieldname": "customer_details_section",
@@ -114,11 +111,15 @@
    "fieldtype": "Link",
    "label": "Bank Account",
    "options": "Bank Account"
+  },
+  {
+   "fieldname": "column_break_8",
+   "fieldtype": "Column Break"
   }
  ],
  "is_submittable": 1,
  "links": [],
- "modified": "2020-04-09 14:44:28.527271",
+ "modified": "2020-04-29 05:20:41.629911",
  "modified_by": "Administrator",
  "module": "Loan Management",
  "name": "Loan Disbursement",
diff --git a/erpnext/loan_management/doctype/loan_disbursement/loan_disbursement.py b/erpnext/loan_management/doctype/loan_disbursement/loan_disbursement.py
index 2918486..c9e36a8 100644
--- a/erpnext/loan_management/doctype/loan_disbursement/loan_disbursement.py
+++ b/erpnext/loan_management/doctype/loan_disbursement/loan_disbursement.py
@@ -84,7 +84,7 @@
 		gle_map.append(
 			self.get_gl_dict({
 				"account": loan_details.loan_account,
-				"against": loan_details.applicant,
+				"against": loan_details.payment_account,
 				"debit": self.disbursed_amount,
 				"debit_in_account_currency": self.disbursed_amount,
 				"against_voucher_type": "Loan",
@@ -100,7 +100,7 @@
 		gle_map.append(
 			self.get_gl_dict({
 				"account": loan_details.payment_account,
-				"against": loan_details.applicant,
+				"against": loan_details.loan_account,
 				"credit": self.disbursed_amount,
 				"credit_in_account_currency": self.disbursed_amount,
 				"against_voucher_type": "Loan",
diff --git a/erpnext/loan_management/doctype/loan_repayment/loan_repayment.py b/erpnext/loan_management/doctype/loan_repayment/loan_repayment.py
index 87e8a15..a5ed5de 100644
--- a/erpnext/loan_management/doctype/loan_repayment/loan_repayment.py
+++ b/erpnext/loan_management/doctype/loan_repayment/loan_repayment.py
@@ -106,6 +106,7 @@
 	def allocate_amounts(self, paid_entries):
 		self.set('repayment_details', [])
 		self.principal_amount_paid = 0
+		interest_paid = 0
 
 		if self.amount_paid - self.penalty_amount > 0 and paid_entries:
 			interest_paid = self.amount_paid - self.penalty_amount
@@ -286,7 +287,11 @@
 	pending_principal_amount = against_loan_doc.total_payment - against_loan_doc.total_principal_paid - against_loan_doc.total_interest_payable
 
 	if payment_type == "Loan Closure" and not payable_principal_amount:
-		pending_days = date_diff(posting_date, entry.posting_date) + 1
+		if final_due_date:
+			pending_days = date_diff(posting_date, final_due_date)
+		else:
+			pending_days = date_diff(posting_date, against_loan_doc.disbursement_date) + 1
+
 		payable_principal_amount = pending_principal_amount
 		per_day_interest = (payable_principal_amount * (loan_type_details.rate_of_interest / 100))/365
 		total_pending_interest += (pending_days * per_day_interest)
diff --git a/erpnext/loan_management/doctype/loan_security/loan_security.json b/erpnext/loan_management/doctype/loan_security/loan_security.json
index e6984ee..1d0bb30 100644
--- a/erpnext/loan_management/doctype/loan_security/loan_security.json
+++ b/erpnext/loan_management/doctype/loan_security/loan_security.json
@@ -1,23 +1,26 @@
 {
- "autoname": "field:loan_security_name",
+ "actions": [],
+ "allow_rename": 1,
  "creation": "2019-09-02 15:07:08.885593",
  "doctype": "DocType",
  "editable_grid": 1,
  "engine": "InnoDB",
  "field_order": [
-  "loan_security_type",
-  "loan_security_code",
   "loan_security_name",
-  "unit_of_measure",
-  "column_break_3",
   "haircut",
+  "loan_security_code",
+  "column_break_3",
+  "loan_security_type",
+  "unit_of_measure",
   "disabled"
  ],
  "fields": [
   {
    "fieldname": "loan_security_name",
    "fieldtype": "Data",
+   "in_list_view": 1,
    "label": "Loan Security Name",
+   "reqd": 1,
    "unique": 1
   },
   {
@@ -33,8 +36,10 @@
   {
    "fieldname": "loan_security_type",
    "fieldtype": "Link",
+   "in_list_view": 1,
    "label": "Loan Security Type",
-   "options": "Loan Security Type"
+   "options": "Loan Security Type",
+   "reqd": 1
   },
   {
    "fieldname": "loan_security_code",
@@ -52,11 +57,15 @@
    "fetch_from": "loan_security_type.unit_of_measure",
    "fieldname": "unit_of_measure",
    "fieldtype": "Link",
+   "in_list_view": 1,
    "label": "Unit Of Measure",
-   "options": "UOM"
+   "options": "UOM",
+   "read_only": 1,
+   "reqd": 1
   }
  ],
- "modified": "2019-11-16 11:36:37.901656",
+ "links": [],
+ "modified": "2020-04-29 13:21:26.043492",
  "modified_by": "Administrator",
  "module": "Loan Management",
  "name": "Loan Security",
@@ -87,7 +96,6 @@
    "write": 1
   }
  ],
- "quick_entry": 1,
  "search_fields": "loan_security_code",
  "sort_field": "modified",
  "sort_order": "DESC",
diff --git a/erpnext/loan_management/doctype/loan_security/loan_security.py b/erpnext/loan_management/doctype/loan_security/loan_security.py
index 800ad12..8858c81 100644
--- a/erpnext/loan_management/doctype/loan_security/loan_security.py
+++ b/erpnext/loan_management/doctype/loan_security/loan_security.py
@@ -7,4 +7,5 @@
 from frappe.model.document import Document
 
 class LoanSecurity(Document):
-	pass
+	def autoname(self):
+		self.name = self.loan_security_name
diff --git a/erpnext/loan_management/doctype/loan_security_pledge/loan_security_pledge.py b/erpnext/loan_management/doctype/loan_security_pledge/loan_security_pledge.py
index b405cca..eb61358 100644
--- a/erpnext/loan_management/doctype/loan_security_pledge/loan_security_pledge.py
+++ b/erpnext/loan_management/doctype/loan_security_pledge/loan_security_pledge.py
@@ -30,7 +30,8 @@
 			if not pledge.qty and not pledge.amount:
 				frappe.throw(_("Qty or Amount is mandatroy for loan security"))
 
-			pledge.loan_security_price = get_loan_security_price(pledge.loan_security)
+			if not (self.loan_application and pledge.loan_security_price):
+				pledge.loan_security_price = get_loan_security_price(pledge.loan_security)
 
 			if not pledge.qty:
 				pledge.qty = cint(pledge.amount/pledge.loan_security_price)
diff --git a/erpnext/loan_management/doctype/loan_security_price/loan_security_price.py b/erpnext/loan_management/doctype/loan_security_price/loan_security_price.py
index 2855b52..32d81af 100644
--- a/erpnext/loan_management/doctype/loan_security_price/loan_security_price.py
+++ b/erpnext/loan_management/doctype/loan_security_price/loan_security_price.py
@@ -37,7 +37,7 @@
 	}, 'loan_security_price')
 
 	if not loan_security_price:
-		frappe.throw(_("No valid <b>Loan Security Price</b> found for {0}").format(frappe.bold(loan_security)))
+		frappe.throw(_("No valid Loan Security Price found for {0}").format(frappe.bold(loan_security)))
 	else:
 		return loan_security_price
 
diff --git a/erpnext/loan_management/doctype/loan_security_type/loan_security_type.json b/erpnext/loan_management/doctype/loan_security_type/loan_security_type.json
index 5f29609..f46b88c 100644
--- a/erpnext/loan_management/doctype/loan_security_type/loan_security_type.json
+++ b/erpnext/loan_management/doctype/loan_security_type/loan_security_type.json
@@ -9,9 +9,9 @@
   "loan_security_type",
   "unit_of_measure",
   "haircut",
-  "disabled",
   "column_break_5",
-  "loan_to_value_ratio"
+  "loan_to_value_ratio",
+  "disabled"
  ],
  "fields": [
   {
@@ -23,7 +23,9 @@
   {
    "fieldname": "loan_security_type",
    "fieldtype": "Data",
+   "in_list_view": 1,
    "label": "Loan Security Type",
+   "reqd": 1,
    "unique": 1
   },
   {
@@ -34,8 +36,10 @@
   {
    "fieldname": "unit_of_measure",
    "fieldtype": "Link",
+   "in_list_view": 1,
    "label": "Unit Of Measure",
-   "options": "UOM"
+   "options": "UOM",
+   "reqd": 1
   },
   {
    "fieldname": "column_break_5",
@@ -48,7 +52,7 @@
   }
  ],
  "links": [],
- "modified": "2020-02-28 12:43:20.364447",
+ "modified": "2020-04-28 14:06:49.046177",
  "modified_by": "Administrator",
  "module": "Loan Management",
  "name": "Loan Security Type",
diff --git a/erpnext/manufacturing/doctype/bom/bom.py b/erpnext/manufacturing/doctype/bom/bom.py
index 6ccd12a..b1fc4de 100644
--- a/erpnext/manufacturing/doctype/bom/bom.py
+++ b/erpnext/manufacturing/doctype/bom/bom.py
@@ -193,7 +193,7 @@
 					if self.rm_cost_as_per == 'Valuation Rate':
 						rate = self.get_valuation_rate(arg) * (arg.get("conversion_factor") or 1)
 					elif self.rm_cost_as_per == 'Last Purchase Rate':
-						rate = (arg.get('last_purchase_rate') \
+						rate = flt(arg.get('last_purchase_rate') \
 							or frappe.db.get_value("Item", arg['item_code'], "last_purchase_rate")) \
 								* (arg.get("conversion_factor") or 1)
 					elif self.rm_cost_as_per == "Price List":
@@ -246,12 +246,13 @@
 			if rate:
 				d.rate = rate
 			d.amount = flt(d.rate) * flt(d.qty)
+			d.db_update()
 
 		if self.docstatus == 1:
 			self.flags.ignore_validate_update_after_submit = True
 			self.calculate_cost()
 		if save:
-			self.save()
+			self.db_update()
 		self.update_exploded_items()
 
 		# update parent BOMs
diff --git a/erpnext/manufacturing/doctype/bom_update_tool/bom_update_tool.py b/erpnext/manufacturing/doctype/bom_update_tool/bom_update_tool.py
index 2758a42..e6c10ad 100644
--- a/erpnext/manufacturing/doctype/bom_update_tool/bom_update_tool.py
+++ b/erpnext/manufacturing/doctype/bom_update_tool/bom_update_tool.py
@@ -82,7 +82,7 @@
 
 @frappe.whitelist()
 def enqueue_update_cost():
-	frappe.enqueue("erpnext.manufacturing.doctype.bom_update_tool.bom_update_tool.update_cost")
+	frappe.enqueue("erpnext.manufacturing.doctype.bom_update_tool.bom_update_tool.update_cost", timeout=40000)
 	frappe.msgprint(_("Queued for updating latest price in all Bill of Materials. It may take a few minutes."))
 
 def update_latest_price_in_all_boms():
@@ -98,6 +98,9 @@
 	doc.replace_bom()
 
 def update_cost():
+	frappe.db.auto_commit_on_many_writes = 1
 	bom_list = get_boms_in_bottom_up_order()
 	for bom in bom_list:
-		frappe.get_doc("BOM", bom).update_cost(update_parent=False, from_child_bom=True)
\ No newline at end of file
+		frappe.get_doc("BOM", bom).update_cost(update_parent=False, from_child_bom=True)
+
+	frappe.db.auto_commit_on_many_writes = 0
\ No newline at end of file
diff --git a/erpnext/manufacturing/doctype/bom_update_tool/test_bom_update_tool.py b/erpnext/manufacturing/doctype/bom_update_tool/test_bom_update_tool.py
index 154addf..ac9a409 100644
--- a/erpnext/manufacturing/doctype/bom_update_tool/test_bom_update_tool.py
+++ b/erpnext/manufacturing/doctype/bom_update_tool/test_bom_update_tool.py
@@ -5,6 +5,9 @@
 from __future__ import unicode_literals
 import unittest
 import frappe
+from erpnext.stock.doctype.item.test_item import create_item
+from erpnext.manufacturing.doctype.production_plan.test_production_plan import make_bom
+from erpnext.manufacturing.doctype.bom_update_tool.bom_update_tool import update_cost
 
 test_records = frappe.get_test_records('BOM')
 
@@ -27,4 +30,31 @@
 		# reverse, as it affects other testcases
 		update_tool.current_bom = bom_doc.name
 		update_tool.new_bom = current_bom
-		update_tool.replace_bom()
\ No newline at end of file
+		update_tool.replace_bom()
+
+	def test_bom_cost(self):
+		for item in ["BOM Cost Test Item 1", "BOM Cost Test Item 2", "BOM Cost Test Item 3"]:
+			item_doc = create_item(item, valuation_rate=100)
+			if item_doc.valuation_rate != 100.00:
+				frappe.db.set_value("Item", item_doc.name, "valuation_rate", 100)
+
+		bom_no = frappe.db.get_value('BOM', {'item': 'BOM Cost Test Item 1'}, "name")
+		if not bom_no:
+			doc = make_bom(item = 'BOM Cost Test Item 1',
+				raw_materials =['BOM Cost Test Item 2', 'BOM Cost Test Item 3'], currency="INR")
+		else:
+			doc = frappe.get_doc("BOM", bom_no)
+
+		self.assertEquals(doc.total_cost, 200)
+
+		frappe.db.set_value("Item", "BOM Cost Test Item 2", "valuation_rate", 200)
+		update_cost()
+
+		doc.load_from_db()
+		self.assertEquals(doc.total_cost, 300)
+
+		frappe.db.set_value("Item", "BOM Cost Test Item 2", "valuation_rate", 100)
+		update_cost()
+
+		doc.load_from_db()
+		self.assertEquals(doc.total_cost, 200)
diff --git a/erpnext/manufacturing/doctype/material_request_plan_item/material_request_plan_item.json b/erpnext/manufacturing/doctype/material_request_plan_item/material_request_plan_item.json
index f27197d..f93b244 100644
--- a/erpnext/manufacturing/doctype/material_request_plan_item/material_request_plan_item.json
+++ b/erpnext/manufacturing/doctype/material_request_plan_item/material_request_plan_item.json
@@ -1,4 +1,5 @@
 {
+ "actions": [],
  "creation": "2017-12-01 12:12:55.048691",
  "doctype": "DocType",
  "editable_grid": 1,
@@ -6,8 +7,9 @@
  "field_order": [
   "item_code",
   "item_name",
-  "warehouse",
   "material_request_type",
+  "from_warehouse",
+  "warehouse",
   "column_break_4",
   "quantity",
   "uom",
@@ -46,6 +48,7 @@
   {
    "fieldname": "material_request_type",
    "fieldtype": "Select",
+   "in_list_view": 1,
    "label": "Material Request Type",
    "options": "\nPurchase\nMaterial Transfer\nMaterial Issue\nManufacture\nCustomer Provided"
   },
@@ -64,11 +67,11 @@
   {
    "fieldname": "projected_qty",
    "fieldtype": "Float",
-   "in_list_view": 1,
    "label": "Projected Qty",
    "read_only": 1
   },
   {
+   "default": "0",
    "fieldname": "actual_qty",
    "fieldtype": "Float",
    "in_list_view": 1,
@@ -119,10 +122,18 @@
    "label": "UOM",
    "options": "UOM",
    "read_only": 1
+  },
+  {
+   "depends_on": "eval:doc.material_request_type == 'Material Transfer'",
+   "fieldname": "from_warehouse",
+   "fieldtype": "Link",
+   "label": "From Warehouse",
+   "options": "Warehouse"
   }
  ],
  "istable": 1,
- "modified": "2019-11-08 15:15:43.979360",
+ "links": [],
+ "modified": "2020-02-03 12:22:29.913302",
  "modified_by": "Administrator",
  "module": "Manufacturing",
  "name": "Material Request Plan Item",
diff --git a/erpnext/manufacturing/doctype/production_plan/production_plan.js b/erpnext/manufacturing/doctype/production_plan/production_plan.js
index b49b0ba..64c952b 100644
--- a/erpnext/manufacturing/doctype/production_plan/production_plan.js
+++ b/erpnext/manufacturing/doctype/production_plan/production_plan.js
@@ -19,7 +19,8 @@
 		frm.set_query('for_warehouse', function(doc) {
 			return {
 				filters: {
-					company: doc.company
+					company: doc.company,
+					is_group: 0
 				}
 			}
 		});
@@ -188,12 +189,53 @@
 	},
 
 	get_items_for_mr: function(frm) {
-		const set_fields = ['actual_qty', 'item_code','item_name', 'description', 'uom',
+		if (!frm.doc.for_warehouse) {
+			frappe.throw(__("Select warehouse for material requests"));
+		}
+
+		if (frm.doc.ignore_existing_ordered_qty) {
+			frm.events.get_items_for_material_requests(frm);
+		} else {
+			const title = __("Transfer Materials For Warehouse {0}", [frm.doc.for_warehouse]);
+			var dialog = new frappe.ui.Dialog({
+				title: title,
+				fields: [
+					{
+						"fieldtype": "Table MultiSelect", "label": __("Source Warehouses"),
+						"fieldname": "warehouses", "options": "Production Plan Material Request Warehouse",
+						"description": "System will pickup the materials from the selected warehouses",
+						get_query: function () {
+							return {
+								filters: {
+									company: frm.doc.company
+								}
+							};
+						},
+					},
+				]
+			});
+
+			dialog.show();
+
+			dialog.set_primary_action(__("Get Items"), () => {
+				let warehouses = dialog.get_values().warehouses;
+				frm.events.get_items_for_material_requests(frm, warehouses);
+				dialog.hide();
+			});
+		}
+	},
+
+	get_items_for_material_requests: function(frm, warehouses) {
+		const set_fields = ['actual_qty', 'item_code','item_name', 'description', 'uom', 'from_warehouse',
 			'min_order_qty', 'quantity', 'sales_order', 'warehouse', 'projected_qty', 'material_request_type'];
+
 		frappe.call({
 			method: "erpnext.manufacturing.doctype.production_plan.production_plan.get_items_for_material_requests",
 			freeze: true,
-			args: {doc: frm.doc},
+			args: {
+				doc: frm.doc,
+				warehouses: warehouses || []
+			},
 			callback: function(r) {
 				if(r.message) {
 					frm.set_value('mr_items', []);
@@ -212,14 +254,14 @@
 	},
 
 	for_warehouse: function(frm) {
-		if (frm.doc.mr_items) {
+		if (frm.doc.mr_items && frm.doc.for_warehouse) {
 			frm.trigger("get_items_for_mr");
 		}
 	},
 
 	download_materials_required: function(frm) {
 		let get_template_url = 'erpnext.manufacturing.doctype.production_plan.production_plan.download_raw_materials';
-		open_url_post(frappe.request.url, { cmd: get_template_url, production_plan: frm.doc.name });
+		open_url_post(frappe.request.url, { cmd: get_template_url, doc: frm.doc });
 	},
 
 	show_progress: function(frm) {
diff --git a/erpnext/manufacturing/doctype/production_plan/production_plan.json b/erpnext/manufacturing/doctype/production_plan/production_plan.json
index 77ca6b6..90e8b22 100644
--- a/erpnext/manufacturing/doctype/production_plan/production_plan.json
+++ b/erpnext/manufacturing/doctype/production_plan/production_plan.json
@@ -43,6 +43,7 @@
   "total_produced_qty",
   "column_break_32",
   "status",
+  "warehouses",
   "amended_from"
  ],
  "fields": [
@@ -219,12 +220,6 @@
    "fieldtype": "Column Break"
   },
   {
-   "fieldname": "for_warehouse",
-   "fieldtype": "Link",
-   "label": "For Warehouse",
-   "options": "Warehouse"
-  },
-  {
    "depends_on": "eval:!doc.__islocal",
    "fieldname": "download_materials_required",
    "fieldtype": "Button",
@@ -292,12 +287,26 @@
    "options": "Production Plan",
    "print_hide": 1,
    "read_only": 1
+  },
+  {
+   "fieldname": "for_warehouse",
+   "fieldtype": "Link",
+   "label": "Material Request Warehouse",
+   "options": "Warehouse"
+  },
+  {
+   "fieldname": "warehouses",
+   "fieldtype": "Table MultiSelect",
+   "hidden": 1,
+   "label": "Warehouses",
+   "options": "Production Plan Material Request Warehouse",
+   "read_only": 1
   }
  ],
  "icon": "fa fa-calendar",
  "is_submittable": 1,
  "links": [],
- "modified": "2020-01-21 19:13:10.113854",
+ "modified": "2020-02-03 00:25:25.934202",
  "modified_by": "Administrator",
  "module": "Manufacturing",
  "name": "Production Plan",
diff --git a/erpnext/manufacturing/doctype/production_plan/production_plan.py b/erpnext/manufacturing/doctype/production_plan/production_plan.py
index 358a542..560286e 100644
--- a/erpnext/manufacturing/doctype/production_plan/production_plan.py
+++ b/erpnext/manufacturing/doctype/production_plan/production_plan.py
@@ -3,7 +3,7 @@
 # For license information, please see license.txt
 
 from __future__ import unicode_literals
-import frappe, json
+import frappe, json, copy
 from frappe import msgprint, _
 from six import string_types, iteritems
 
@@ -346,6 +346,7 @@
 		if not wo.fg_warehouse:
 			wo.fg_warehouse = warehouse.get('fg_warehouse')
 		try:
+			wo.flags.ignore_mandatory = True
 			wo.insert()
 			return wo.name
 		except OverProductionError:
@@ -384,6 +385,7 @@
 			# add item
 			material_request.append("items", {
 				"item_code": item.item_code,
+				"from_warehouse": item.from_warehouse,
 				"qty": item.quantity,
 				"schedule_date": schedule_date,
 				"warehouse": item.warehouse,
@@ -414,19 +416,18 @@
 			msgprint(_("No material request created"))
 
 @frappe.whitelist()
-def download_raw_materials(production_plan):
-	doc = frappe.get_doc('Production Plan', production_plan)
-	doc.check_permission()
+def download_raw_materials(doc):
+	if isinstance(doc, string_types):
+		doc = frappe._dict(json.loads(doc))
 
 	item_list = [['Item Code', 'Description', 'Stock UOM', 'Required Qty', 'Warehouse',
 		'projected Qty', 'Actual Qty']]
 
-	doc = doc.as_dict()
-	for d in get_items_for_material_requests(doc, ignore_existing_ordered_qty=True):
+	for d in get_items_for_material_requests(doc):
 		item_list.append([d.get('item_code'), d.get('description'), d.get('stock_uom'), d.get('quantity'),
 			d.get('warehouse'), d.get('projected_qty'), d.get('actual_qty')])
 
-		if not doc.for_warehouse:
+		if not doc.get('for_warehouse'):
 			row = {'item_code': d.get('item_code')}
 			for bin_dict in get_bin_details(row, doc.company, all_warehouse=True):
 				if d.get("warehouse") == bin_dict.get('warehouse'):
@@ -609,26 +610,43 @@
 	""".format(conditions=conditions), { "item_code": row['item_code'] }, as_dict=1)
 
 @frappe.whitelist()
-def get_items_for_material_requests(doc, ignore_existing_ordered_qty=None):
+def get_items_for_material_requests(doc, warehouses=None):
 	if isinstance(doc, string_types):
 		doc = frappe._dict(json.loads(doc))
 
+	warehouse_list = []
+	if warehouses:
+		if isinstance(warehouses, string_types):
+			warehouses = json.loads(warehouses)
+
+		for row in warehouses:
+			child_warehouses = frappe.db.get_descendants('Warehouse', row.get("warehouse"))
+			if child_warehouses:
+				warehouse_list.extend(child_warehouses)
+			else:
+				warehouse_list.append(row.get("warehouse"))
+
+	if warehouse_list:
+		warehouses = list(set(warehouse_list))
+	
+		if doc.get("for_warehouse") and doc.get("for_warehouse") in warehouses:
+			warehouses.remove(doc.get("for_warehouse"))
+
+		warehouse_list = None
+
 	doc['mr_items'] = []
 	po_items = doc.get('po_items') if doc.get('po_items') else doc.get('items')
 	if not po_items:
 		frappe.throw(_("Items are required to pull the raw materials which is associated with it."))
 
 	company = doc.get('company')
-	warehouse = doc.get('for_warehouse')
-
-	if not ignore_existing_ordered_qty:
-		ignore_existing_ordered_qty = doc.get('ignore_existing_ordered_qty')
+	ignore_existing_ordered_qty = doc.get('ignore_existing_ordered_qty')
 
 	so_item_details = frappe._dict()
 	for data in po_items:
 		planned_qty = data.get('required_qty') or data.get('planned_qty')
 		ignore_existing_ordered_qty = data.get('ignore_existing_ordered_qty') or ignore_existing_ordered_qty
-		warehouse = data.get("warehouse") or warehouse
+		warehouse = doc.get('for_warehouse')
 
 		item_details = {}
 		if data.get("bom") or data.get("bom_no"):
@@ -699,12 +717,51 @@
 				if items:
 					mr_items.append(items)
 
+	if not ignore_existing_ordered_qty and warehouses:
+		new_mr_items = []
+		for item in mr_items:
+			get_materials_from_other_locations(item, warehouses, new_mr_items, company)
+
+		mr_items = new_mr_items
+
 	if not mr_items:
-		frappe.msgprint(_("""As raw materials projected quantity is more than required quantity, there is no need to create material request.
-			Still if you want to make material request, kindly enable <b>Ignore Existing Projected Quantity</b> checkbox"""))
+		frappe.msgprint(_("""As raw materials projected quantity is more than required quantity,
+			there is no need to create material request for the warehouse {0}.
+			Still if you want to make material request,
+			kindly enable <b>Ignore Existing Projected Quantity</b> checkbox""").format(doc.get('for_warehouse')))
 
 	return mr_items
 
+def get_materials_from_other_locations(item, warehouses, new_mr_items, company):
+	from erpnext.stock.doctype.pick_list.pick_list import get_available_item_locations
+	locations = get_available_item_locations(item.get("item_code"),
+		warehouses, item.get("quantity"), company, ignore_validation=True)
+
+	if not locations:
+		new_mr_items.append(item)
+		return
+
+	required_qty = item.get("quantity")
+	for d in locations:
+		if required_qty <=0: return
+
+		new_dict = copy.deepcopy(item)
+		quantity = required_qty if d.get("qty") > required_qty else d.get("qty")
+
+		if required_qty > 0:
+			new_dict.update({
+				"quantity": quantity,
+				"material_request_type": "Material Transfer",
+				"from_warehouse": d.get("warehouse")
+			})
+
+			required_qty -= quantity
+			new_mr_items.append(new_dict)
+
+	if required_qty:
+		item["quantity"] = required_qty
+		new_mr_items.append(item)
+
 @frappe.whitelist()
 def get_item_data(item_code):
 	item_details = get_item_details(item_code)
diff --git a/erpnext/manufacturing/doctype/production_plan/test_production_plan.py b/erpnext/manufacturing/doctype/production_plan/test_production_plan.py
index f70c9cc..ca67d71 100644
--- a/erpnext/manufacturing/doctype/production_plan/test_production_plan.py
+++ b/erpnext/manufacturing/doctype/production_plan/test_production_plan.py
@@ -62,9 +62,9 @@
 
 	def test_production_plan_for_existing_ordered_qty(self):
 		sr1 = create_stock_reconciliation(item_code="Raw Material Item 1",
-			target="_Test Warehouse - _TC", qty=1, rate=100)
+			target="_Test Warehouse - _TC", qty=1, rate=110)
 		sr2 = create_stock_reconciliation(item_code="Raw Material Item 2",
-			target="_Test Warehouse - _TC", qty=1, rate=100)
+			target="_Test Warehouse - _TC", qty=1, rate=120)
 
 		pln = create_production_plan(item_code='Test Production Item 1', ignore_existing_ordered_qty=0)
 		self.assertTrue(len(pln.mr_items), 1)
@@ -86,9 +86,9 @@
 
 	def test_production_plan_without_multi_level_for_existing_ordered_qty(self):
 		sr1 = create_stock_reconciliation(item_code="Raw Material Item 1",
-			target="_Test Warehouse - _TC", qty=1, rate=100)
+			target="_Test Warehouse - _TC", qty=1, rate=130)
 		sr2 = create_stock_reconciliation(item_code="Subassembly Item 1",
-			target="_Test Warehouse - _TC", qty=1, rate=100)
+			target="_Test Warehouse - _TC", qty=1, rate=140)
 
 		pln = create_production_plan(item_code='Test Production Item 1',
 			use_multi_level_bom=0, ignore_existing_ordered_qty=0)
@@ -192,9 +192,10 @@
 	args = frappe._dict(args)
 
 	bom = frappe.get_doc({
-		'doctype': "BOM",
+		'doctype': 'BOM',
 		'is_default': 1,
 		'item': args.item,
+		'currency': args.currency or 'USD',
 		'quantity': args.quantity or 1,
 		'company': args.company or '_Test Company'
 	})
@@ -211,4 +212,5 @@
 		})
 
 	bom.insert(ignore_permissions=True)
-	bom.submit()
\ No newline at end of file
+	bom.submit()
+	return bom
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/account_subtype/__init__.py b/erpnext/manufacturing/doctype/production_plan_material_request_warehouse/__init__.py
similarity index 100%
copy from erpnext/accounts/doctype/account_subtype/__init__.py
copy to erpnext/manufacturing/doctype/production_plan_material_request_warehouse/__init__.py
diff --git a/erpnext/manufacturing/doctype/production_plan_material_request_warehouse/production_plan_material_request_warehouse.js b/erpnext/manufacturing/doctype/production_plan_material_request_warehouse/production_plan_material_request_warehouse.js
new file mode 100644
index 0000000..53f8758
--- /dev/null
+++ b/erpnext/manufacturing/doctype/production_plan_material_request_warehouse/production_plan_material_request_warehouse.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('Production Plan Material Request Warehouse', {
+	// refresh: function(frm) {
+
+	// }
+});
diff --git a/erpnext/manufacturing/doctype/production_plan_material_request_warehouse/production_plan_material_request_warehouse.json b/erpnext/manufacturing/doctype/production_plan_material_request_warehouse/production_plan_material_request_warehouse.json
new file mode 100644
index 0000000..53e33c0
--- /dev/null
+++ b/erpnext/manufacturing/doctype/production_plan_material_request_warehouse/production_plan_material_request_warehouse.json
@@ -0,0 +1,42 @@
+{
+ "actions": [],
+ "creation": "2020-02-02 10:37:16.650836",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "warehouse"
+ ],
+ "fields": [
+  {
+   "fieldname": "warehouse",
+   "fieldtype": "Link",
+   "label": "Warehouse",
+   "options": "Warehouse"
+  }
+ ],
+ "links": [],
+ "modified": "2020-02-02 10:37:16.650836",
+ "modified_by": "Administrator",
+ "module": "Manufacturing",
+ "name": "Production Plan Material Request Warehouse",
+ "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/manufacturing/doctype/production_plan_material_request_warehouse/production_plan_material_request_warehouse.py b/erpnext/manufacturing/doctype/production_plan_material_request_warehouse/production_plan_material_request_warehouse.py
new file mode 100644
index 0000000..f605985
--- /dev/null
+++ b/erpnext/manufacturing/doctype/production_plan_material_request_warehouse/production_plan_material_request_warehouse.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 ProductionPlanMaterialRequestWarehouse(Document):
+	pass
diff --git a/erpnext/manufacturing/doctype/production_plan_material_request_warehouse/test_production_plan_material_request_warehouse.py b/erpnext/manufacturing/doctype/production_plan_material_request_warehouse/test_production_plan_material_request_warehouse.py
new file mode 100644
index 0000000..ecab5fb
--- /dev/null
+++ b/erpnext/manufacturing/doctype/production_plan_material_request_warehouse/test_production_plan_material_request_warehouse.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 TestProductionPlanMaterialRequestWarehouse(unittest.TestCase):
+	pass
diff --git a/erpnext/manufacturing/doctype/work_order/work_order.js b/erpnext/manufacturing/doctype/work_order/work_order.js
index 894761b..c125571 100644
--- a/erpnext/manufacturing/doctype/work_order/work_order.js
+++ b/erpnext/manufacturing/doctype/work_order/work_order.js
@@ -400,7 +400,6 @@
 	},
 
 	before_submit: function(frm) {
-		frm.toggle_reqd(["fg_warehouse", "wip_warehouse"], true);
 		frm.fields_dict.required_items.grid.toggle_reqd("source_warehouse", true);
 		frm.toggle_reqd("transfer_material_against",
 			frm.doc.operations && frm.doc.operations.length > 0);
diff --git a/erpnext/manufacturing/doctype/work_order/work_order.json b/erpnext/manufacturing/doctype/work_order/work_order.json
index e6990fd..00a67a0 100644
--- a/erpnext/manufacturing/doctype/work_order/work_order.json
+++ b/erpnext/manufacturing/doctype/work_order/work_order.json
@@ -231,6 +231,7 @@
    "fieldname": "wip_warehouse",
    "fieldtype": "Link",
    "label": "Work-in-Progress Warehouse",
+   "mandatory_depends_on": "eval:!doc.skip_transfer || doc.from_wip_warehouse",
    "options": "Warehouse"
   },
   {
@@ -238,7 +239,8 @@
    "fieldname": "fg_warehouse",
    "fieldtype": "Link",
    "label": "Target Warehouse",
-   "options": "Warehouse"
+   "options": "Warehouse",
+   "reqd": 1
   },
   {
    "fieldname": "column_break_12",
@@ -481,7 +483,7 @@
  "image_field": "image",
  "is_submittable": 1,
  "links": [],
- "modified": "2020-01-31 12:46:23.636033",
+ "modified": "2020-04-24 19:32:43.323054",
  "modified_by": "Administrator",
  "module": "Manufacturing",
  "name": "Work Order",
diff --git a/erpnext/manufacturing/report/bom_stock_report/bom_stock_report.py b/erpnext/manufacturing/report/bom_stock_report/bom_stock_report.py
index 65f4d08..75ebcbc 100644
--- a/erpnext/manufacturing/report/bom_stock_report/bom_stock_report.py
+++ b/erpnext/manufacturing/report/bom_stock_report/bom_stock_report.py
@@ -18,10 +18,10 @@
 	"""return columns"""
 	columns = [
 		_("Item") + ":Link/Item:150",
-		_("Description") + "::500",
-		_("Qty per BOM Line") + ":Float:100",
-		_("Required Qty") + ":Float:100",
-		_("In Stock Qty") + ":Float:100",
+		_("Description") + "::300",
+		_("BOM Qty") + ":Float:160",
+		_("Required Qty") + ":Float:120",
+		_("In Stock Qty") + ":Float:120",
 		_("Enough Parts to Build") + ":Float:200",
 	]
 
@@ -59,13 +59,14 @@
 				bom_item.item_code,
 				bom_item.description ,
 				bom_item.{qty_field},
-				bom_item.{qty_field} * {qty_to_produce},
+				bom_item.{qty_field} * {qty_to_produce} / bom.quantity,
 				sum(ledger.actual_qty) as actual_qty,
-				sum(FLOOR(ledger.actual_qty / (bom_item.{qty_field} * {qty_to_produce})))
+				sum(FLOOR(ledger.actual_qty / (bom_item.{qty_field} * {qty_to_produce} / bom.quantity)))
 			FROM
-				{table} AS bom_item
+				`tabBOM` AS bom INNER JOIN {table} AS bom_item
+					ON bom.name = bom_item.parent
 				LEFT JOIN `tabBin` AS ledger
-				ON bom_item.item_code = ledger.item_code
+					ON bom_item.item_code = ledger.item_code
 				{conditions}
 			WHERE
 				bom_item.parent = '{bom}' and bom_item.parenttype='BOM'
diff --git a/erpnext/non_profit/doctype/member/member_dashboard.py b/erpnext/non_profit/doctype/member/member_dashboard.py
index 945fb7b..743db25 100644
--- a/erpnext/non_profit/doctype/member/member_dashboard.py
+++ b/erpnext/non_profit/doctype/member/member_dashboard.py
@@ -6,10 +6,17 @@
 		'heatmap': True,
 		'heatmap_message': _('Member Activity'),
 		'fieldname': 'member',
+		'non_standard_fieldnames': {
+			'Bank Account': 'party'
+		},
 		'transactions': [
 			{
 				'label': _('Membership Details'),
 				'items': ['Membership']
+			},
+			{
+				'label': _('Fee'),
+				'items': ['Bank Account']
 			}
 		]
-	}
\ No newline at end of file
+	}
diff --git a/erpnext/non_profit/doctype/membership/membership.py b/erpnext/non_profit/doctype/membership/membership.py
index a523a23..5a69cdb 100644
--- a/erpnext/non_profit/doctype/membership/membership.py
+++ b/erpnext/non_profit/doctype/membership/membership.py
@@ -62,11 +62,9 @@
 					'subscription_id': subscription_id,
 					'email_id': email
 				}, order_by="creation desc")
-
 	return frappe.get_doc("Member", members[0]['name'])
 
-
-@frappe.whitelist()
+@frappe.whitelist(allow_guest=True)
 def trigger_razorpay_subscription(data):
 	if isinstance(data, six.string_types):
 		data = json.loads(data)
@@ -88,10 +86,6 @@
 
 	if data.event == "subscription.activated":
 		member.customer_id = payment.customer_id
-		member.subscription_start = datetime.fromtimestamp(subscription.start_at)
-		member.subscription_end = datetime.fromtimestamp(subscription.end_at)
-		member.subscription_activated = 1
-		member.save(ignore_permissions=True)
 	elif data.event == "subscription.charged":
 		membership = frappe.new_doc("Membership")
 		membership.update({
@@ -108,6 +102,12 @@
 		})
 		membership.insert(ignore_permissions=True)
 
+	# Update these values anyway
+	member.subscription_start = datetime.fromtimestamp(subscription.start_at)
+	member.subscription_end = datetime.fromtimestamp(subscription.end_at)
+	member.subscription_activated = 1
+	member.save(ignore_permissions=True)
+
 	return True
 
 
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index 9ef0b8d..5295399 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -1,6 +1,7 @@
 execute:import unidecode # new requirement
 erpnext.patches.v8_0.move_perpetual_inventory_setting
 erpnext.patches.v8_9.set_print_zero_amount_taxes
+erpnext.patches.v12_0.update_is_cancelled_field
 erpnext.patches.v11_0.rename_production_order_to_work_order
 erpnext.patches.v11_0.refactor_naming_series
 erpnext.patches.v11_0.refactor_autoname_naming
@@ -261,7 +262,6 @@
 erpnext.patches.v6_21.fix_reorder_level
 erpnext.patches.v6_21.rename_material_request_fields
 erpnext.patches.v6_23.update_stopped_status_to_closed
-erpnext.patches.v6_24.repost_valuation_rate_for_serialized_items
 erpnext.patches.v6_24.set_recurring_id
 erpnext.patches.v6_20x.set_compact_print
 execute:frappe.delete_doc_if_exists("Web Form", "contact") #2016-03-10
@@ -315,7 +315,6 @@
 erpnext.patches.v7_0.rename_examination_to_assessment
 erpnext.patches.v7_0.set_portal_settings
 erpnext.patches.v7_0.update_change_amount_account
-erpnext.patches.v7_0.repost_future_gle_for_purchase_invoice
 erpnext.patches.v7_0.fix_duplicate_icons
 erpnext.patches.v7_0.repost_gle_for_pos_sales_return
 erpnext.patches.v7_1.update_total_billing_hours
@@ -644,6 +643,7 @@
 erpnext.patches.v12_0.set_cwip_and_delete_asset_settings
 erpnext.patches.v12_0.set_expense_account_in_landed_cost_voucher_taxes
 erpnext.patches.v12_0.replace_accounting_with_accounts_in_home_settings
+erpnext.patches.v12_0.set_automatically_process_deferred_accounting_in_accounts_settings
 erpnext.patches.v12_0.set_payment_entry_status
 erpnext.patches.v12_0.update_owner_fields_in_acc_dimension_custom_fields
 erpnext.patches.v12_0.add_export_type_field_in_party_master
@@ -660,10 +660,20 @@
 erpnext.patches.v12_0.set_job_offer_applicant_email
 erpnext.patches.v12_0.create_irs_1099_field_united_states
 erpnext.patches.v12_0.move_bank_account_swift_number_to_bank
+erpnext.patches.v12_0.rename_bank_reconciliation
 erpnext.patches.v12_0.rename_bank_reconciliation_fields # 2020-01-22
+erpnext.patches.v12_0.add_permission_in_lower_deduction
 erpnext.patches.v12_0.set_received_qty_in_material_request_as_per_stock_uom
+erpnext.patches.v12_0.rename_account_type_doctype
 erpnext.patches.v12_0.recalculate_requested_qty_in_bin
 erpnext.patches.v12_0.update_healthcare_refactored_changes
 erpnext.patches.v12_0.set_total_batch_quantity
 erpnext.patches.v12_0.rename_mws_settings_fields
 erpnext.patches.v12_0.set_updated_purpose_in_pick_list
+erpnext.patches.v12_0.set_default_payroll_based_on
+erpnext.patches.v12_0.repost_stock_ledger_entries_for_target_warehouse
+erpnext.patches.v12_0.update_end_date_and_status_in_email_campaign
+erpnext.patches.v13_0.move_tax_slabs_from_payroll_period_to_income_tax_slab #123
+erpnext.patches.v12_0.fix_quotation_expired_status
+erpnext.patches.v12_0.update_appointment_reminder_scheduler_entry
+erpnext.patches.v12_0.retain_permission_rules_for_video_doctype
diff --git a/erpnext/patches/v10_0/repost_gle_for_purchase_receipts_with_rejected_items.py b/erpnext/patches/v10_0/repost_gle_for_purchase_receipts_with_rejected_items.py
index 68c06ef..e6546e3 100644
--- a/erpnext/patches/v10_0/repost_gle_for_purchase_receipts_with_rejected_items.py
+++ b/erpnext/patches/v10_0/repost_gle_for_purchase_receipts_with_rejected_items.py
@@ -24,9 +24,9 @@
 			doc = frappe.get_doc("Purchase Receipt", d.name)
 
 			doc.docstatus = 2
-			doc.make_gl_entries_on_cancel(repost_future_gle=False)
+			doc.make_gl_entries_on_cancel()
 
 
 			# update gl entries for submit state of PR
 			doc.docstatus = 1
-			doc.make_gl_entries(repost_future_gle=False)
+			doc.make_gl_entries()
diff --git a/erpnext/patches/v10_0/taxes_issue_with_pos.py b/erpnext/patches/v10_0/taxes_issue_with_pos.py
index 9b54297..2a3275a 100644
--- a/erpnext/patches/v10_0/taxes_issue_with_pos.py
+++ b/erpnext/patches/v10_0/taxes_issue_with_pos.py
@@ -19,7 +19,7 @@
 			doc.db_update()
 
 			delete_gle_for_voucher(doc.name)
-			doc.make_gl_entries(repost_future_gle=False)
+			doc.make_gl_entries()
 
 def delete_gle_for_voucher(voucher_no):
 	frappe.db.sql("""delete from `tabGL Entry` where voucher_no = %(voucher_no)s""",
diff --git a/erpnext/patches/v11_0/add_permissions_in_gst_settings.py b/erpnext/patches/v11_0/add_permissions_in_gst_settings.py
index 121a202..d793611 100644
--- a/erpnext/patches/v11_0/add_permissions_in_gst_settings.py
+++ b/erpnext/patches/v11_0/add_permissions_in_gst_settings.py
@@ -6,4 +6,5 @@
 	if not company:
 		return
 
+	frappe.reload_doc("regional", "doctype", "lower_deduction_certificate")
 	add_permissions()
\ No newline at end of file
diff --git a/erpnext/patches/v11_0/set_salary_component_properties.py b/erpnext/patches/v11_0/set_salary_component_properties.py
index fa3605b..83fb53d 100644
--- a/erpnext/patches/v11_0/set_salary_component_properties.py
+++ b/erpnext/patches/v11_0/set_salary_component_properties.py
@@ -5,8 +5,7 @@
 	frappe.reload_doc('hr', 'doctype', 'salary_detail')
 	frappe.reload_doc('hr', 'doctype', 'salary_component')
 
-	frappe.db.sql("update `tabSalary Component` set is_payable=1, is_tax_applicable=1 where type='Earning'")
-	frappe.db.sql("update `tabSalary Component` set is_payable=0 where type='Deduction'")
+	frappe.db.sql("update `tabSalary Component` set is_tax_applicable=1 where type='Earning'")
 
 	frappe.db.sql("""update `tabSalary Component` set variable_based_on_taxable_salary=1
 	    where type='Deduction' and name in ('TDS', 'Tax Deducted at Source')""")
diff --git a/erpnext/patches/v12_0/add_default_dashboards.py b/erpnext/patches/v12_0/add_default_dashboards.py
index ab92fba..0c3f2f8 100644
--- a/erpnext/patches/v12_0/add_default_dashboards.py
+++ b/erpnext/patches/v12_0/add_default_dashboards.py
@@ -5,4 +5,5 @@
 from erpnext.setup.setup_wizard.operations.install_fixtures import add_dashboards
 
 def execute():
+	frappe.reload_doc("desk", "doctype", "number_card_link")
 	add_dashboards()
diff --git a/erpnext/patches/v12_0/add_permission_in_lower_deduction.py b/erpnext/patches/v12_0/add_permission_in_lower_deduction.py
new file mode 100644
index 0000000..af9bf74
--- /dev/null
+++ b/erpnext/patches/v12_0/add_permission_in_lower_deduction.py
@@ -0,0 +1,13 @@
+import frappe
+from frappe.permissions import add_permission, update_permission_property
+
+def execute():
+	company = frappe.get_all('Company', filters = {'country': 'India'})
+	if not company:
+		return
+
+	frappe.reload_doc('regional', 'doctype', 'Lower Deduction Certificate')
+
+	add_permission('Lower Deduction Certificate', 'Accounts Manager', 0)
+	update_permission_property('Lower Deduction Certificate', 'Accounts Manager', 0, 'write', 1)
+	update_permission_property('Lower Deduction Certificate', 'Accounts Manager', 0, 'create', 1)
\ No newline at end of file
diff --git a/erpnext/patches/v12_0/create_irs_1099_field_united_states.py b/erpnext/patches/v12_0/create_irs_1099_field_united_states.py
index 3e4c87f..82c8f5c 100644
--- a/erpnext/patches/v12_0/create_irs_1099_field_united_states.py
+++ b/erpnext/patches/v12_0/create_irs_1099_field_united_states.py
@@ -3,8 +3,11 @@
 from erpnext.regional.united_states.setup import make_custom_fields
 
 def execute():
-    company = frappe.get_all('Company', filters = {'country': 'United States'})
-    if not company:
-        return
 
-    make_custom_fields()
\ No newline at end of file
+	frappe.reload_doc('accounts', 'doctype', 'allowed_to_transact_with', force=True)
+
+	company = frappe.get_all('Company', filters = {'country': 'United States'})
+	if not company:
+		return
+
+	make_custom_fields()
\ No newline at end of file
diff --git a/erpnext/patches/v12_0/fix_quotation_expired_status.py b/erpnext/patches/v12_0/fix_quotation_expired_status.py
new file mode 100644
index 0000000..c8708d8
--- /dev/null
+++ b/erpnext/patches/v12_0/fix_quotation_expired_status.py
@@ -0,0 +1,34 @@
+import frappe
+
+def execute():
+	# fixes status of quotations which have status 'Expired' despite having valid sales order created
+
+	# filter out submitted expired quotations which has sales order created
+	cond = "qo.docstatus = 1 and qo.status = 'Expired'"
+	invalid_so_against_quo = """
+		SELECT 
+			so.name FROM `tabSales Order` so, `tabSales Order Item` so_item
+		WHERE 
+			so_item.docstatus = 1 and so.docstatus = 1
+			and so_item.parent = so.name
+			and so_item.prevdoc_docname = qo.name
+			and qo.valid_till < so.transaction_date""" # check if SO was created after quotation expired
+		
+	frappe.db.sql(
+		"""UPDATE `tabQuotation` qo SET qo.status = 'Expired' WHERE {cond} and exists({invalid_so_against_quo})"""
+			.format(cond=cond, invalid_so_against_quo=invalid_so_against_quo)
+		)
+	
+	valid_so_against_quo = """
+		SELECT 
+			so.name FROM `tabSales Order` so, `tabSales Order Item` so_item
+		WHERE 
+			so_item.docstatus = 1 and so.docstatus = 1
+			and so_item.parent = so.name
+			and so_item.prevdoc_docname = qo.name
+			and qo.valid_till >= so.transaction_date""" # check if SO was created before quotation expired
+
+	frappe.db.sql(
+		"""UPDATE `tabQuotation` qo SET qo.status = 'Closed' WHERE {cond} and exists({valid_so_against_quo})"""
+			.format(cond=cond, valid_so_against_quo=valid_so_against_quo)
+		)
diff --git a/erpnext/patches/v12_0/rename_account_type_doctype.py b/erpnext/patches/v12_0/rename_account_type_doctype.py
new file mode 100644
index 0000000..ffb4e93
--- /dev/null
+++ b/erpnext/patches/v12_0/rename_account_type_doctype.py
@@ -0,0 +1,7 @@
+from __future__ import unicode_literals
+import frappe
+
+def execute():
+	frappe.rename_doc('DocType', 'Account Type', 'Bank Account Type', force=True)
+	frappe.rename_doc('DocType', 'Account Subtype', 'Bank Account Subtype', force=True)
+	frappe.reload_doc('accounts', 'doctype', 'bank_account')
\ No newline at end of file
diff --git a/erpnext/patches/v12_0/rename_bank_reconciliation.py b/erpnext/patches/v12_0/rename_bank_reconciliation.py
new file mode 100644
index 0000000..eda47a9
--- /dev/null
+++ b/erpnext/patches/v12_0/rename_bank_reconciliation.py
@@ -0,0 +1,16 @@
+# Copyright (c) 2018, Frappe and Contributors
+# License: GNU General Public License v3. See license.txt
+
+from __future__ import unicode_literals
+import frappe
+
+def execute():
+	if frappe.db.table_exists("Bank Reconciliation"):
+		frappe.rename_doc('DocType', 'Bank Reconciliation', 'Bank Clearance', force=True)
+		frappe.reload_doc('Accounts', 'doctype', 'Bank Clearance')
+		
+		frappe.rename_doc('DocType', 'Bank Reconciliation Detail', 'Bank Clearance Detail', force=True)
+		frappe.reload_doc('Accounts', 'doctype', 'Bank Clearance Detail')
+		
+		frappe.delete_doc("DocType", "Bank Reconciliation")
+		frappe.delete_doc("DocType", "Bank Reconciliation Detail")
diff --git a/erpnext/patches/v12_0/rename_bank_reconciliation_fields.py b/erpnext/patches/v12_0/rename_bank_reconciliation_fields.py
index caeda8a..978b1c9 100644
--- a/erpnext/patches/v12_0/rename_bank_reconciliation_fields.py
+++ b/erpnext/patches/v12_0/rename_bank_reconciliation_fields.py
@@ -9,6 +9,6 @@
 		frappe.db.sql("UPDATE tabSingles SET field='{new_name}' WHERE doctype='{doctype}' AND field='{old_name}';".format(**kwargs)) #nosec
 
 def execute():
-	_rename_single_field(doctype = "Bank Reconciliation", old_name = "bank_account" , new_name = "account")
-	_rename_single_field(doctype = "Bank Reconciliation", old_name = "bank_account_no", new_name = "bank_account")
-	frappe.reload_doc("Accounts", "doctype", "Bank Reconciliation")
+	_rename_single_field(doctype = "Bank Clearance", old_name = "bank_account" , new_name = "account")
+	_rename_single_field(doctype = "Bank Clearance", old_name = "bank_account_no", new_name = "bank_account")
+	frappe.reload_doc("Accounts", "doctype", "Bank Clearance")
diff --git a/erpnext/patches/v12_0/repost_stock_ledger_entries_for_target_warehouse.py b/erpnext/patches/v12_0/repost_stock_ledger_entries_for_target_warehouse.py
new file mode 100644
index 0000000..13e935b
--- /dev/null
+++ b/erpnext/patches/v12_0/repost_stock_ledger_entries_for_target_warehouse.py
@@ -0,0 +1,71 @@
+# Copyright (c) 2020, Frappe and Contributors
+# License: GNU General Public License v3. See license.txt
+
+from __future__ import unicode_literals
+import frappe
+
+def execute():
+	warehouse_perm = frappe.get_all("User Permission",
+		fields=["count(*) as p_count", "is_default", "user"], filters={"allow": "Warehouse"}, group_by="user")
+
+	if not warehouse_perm:
+		return
+
+	execute_patch = False
+	for perm_data in warehouse_perm:
+		if perm_data.p_count == 1 or (perm_data.p_count > 1 and frappe.get_all("User Permission",
+			filters = {"user": perm_data.user, "allow": "warehouse", "is_default": 1}, limit=1)):
+			execute_patch = True
+			break
+
+	if not execute_patch: return
+
+	for doctype in ["Sales Invoice", "Delivery Note"]:
+		if not frappe.get_meta(doctype + ' Item').get_field("target_warehouse").hidden: continue
+
+		cond = ""
+		if doctype == "Sales Invoice":
+			cond = " AND parent_doc.update_stock = 1"
+
+		data = frappe.db.sql(""" SELECT parent_doc.name as name, child_doc.name as child_name
+			FROM
+				`tab{doctype}` parent_doc, `tab{doctype} Item` child_doc
+			WHERE
+				parent_doc.name = child_doc.parent AND parent_doc.docstatus < 2
+				AND child_doc.target_warehouse is not null AND child_doc.target_warehouse != ''
+				AND child_doc.creation > '2020-04-16' {cond}
+		""".format(doctype=doctype, cond=cond), as_dict=1)
+
+		if data:
+			names = [d.child_name for d in data]
+			frappe.db.sql(""" UPDATE `tab{0} Item` set target_warehouse = null
+				WHERE name in ({1}) """.format(doctype, ','.join(["%s"] * len(names) )), tuple(names))
+
+			frappe.db.sql(""" UPDATE `tabPacked Item` set target_warehouse = null
+				WHERE parenttype = '{0}' and parent_detail_docname in ({1})
+			""".format(doctype, ','.join(["%s"] * len(names) )), tuple(names))
+
+			parent_names = list(set([d.name for d in data]))
+
+			for d in parent_names:
+				doc = frappe.get_doc(doctype, d)
+				if doc.docstatus != 1: continue
+
+				doc.docstatus = 2
+				doc.update_stock_ledger()
+				doc.make_gl_entries_on_cancel(repost_future_gle=False)
+
+				# update stock & gl entries for submit state of PR
+				doc.docstatus = 1
+				doc.update_stock_ledger()
+				doc.make_gl_entries()
+
+	if frappe.get_meta('Sales Order Item').get_field("target_warehouse").hidden:
+		frappe.db.sql(""" UPDATE `tabSales Order Item` set target_warehouse = null
+			WHERE creation > '2020-04-16' and docstatus < 2 """)
+
+		frappe.db.sql(""" UPDATE `tabPacked Item` set target_warehouse = null
+			WHERE creation > '2020-04-16' and docstatus < 2 and parenttype = 'Sales Order' """)
+
+
+
diff --git a/erpnext/patches/v12_0/retain_permission_rules_for_video_doctype.py b/erpnext/patches/v12_0/retain_permission_rules_for_video_doctype.py
new file mode 100644
index 0000000..ca8a13b
--- /dev/null
+++ b/erpnext/patches/v12_0/retain_permission_rules_for_video_doctype.py
@@ -0,0 +1,21 @@
+from __future__ import unicode_literals
+import frappe
+
+def execute():
+	# to retain the roles and permissions from Education Module
+	# after moving doctype to core
+	permissions = frappe.db.sql("""
+		SELECT
+			*
+		FROM
+			`tabDocPerm`
+		WHERE
+			parent='Video'
+	""", as_dict=True)
+
+	frappe.reload_doc('core', 'doctype', 'video')
+	doc = frappe.get_doc('DocType', 'Video')
+	doc.permissions = []
+	for perm in permissions:
+		doc.append('permissions', perm)
+	doc.save()
diff --git a/erpnext/patches/v12_0/set_automatically_process_deferred_accounting_in_accounts_settings.py b/erpnext/patches/v12_0/set_automatically_process_deferred_accounting_in_accounts_settings.py
new file mode 100644
index 0000000..5ee75be
--- /dev/null
+++ b/erpnext/patches/v12_0/set_automatically_process_deferred_accounting_in_accounts_settings.py
@@ -0,0 +1,7 @@
+from __future__ import unicode_literals
+import frappe
+
+def execute():
+	frappe.reload_doc("accounts", "doctype", "accounts_settings")
+
+	frappe.db.set_value("Accounts Settings", None, "automatically_process_deferred_accounting_entry", 1)
\ No newline at end of file
diff --git a/erpnext/patches/v12_0/set_default_payroll_based_on.py b/erpnext/patches/v12_0/set_default_payroll_based_on.py
new file mode 100644
index 0000000..04b54a6
--- /dev/null
+++ b/erpnext/patches/v12_0/set_default_payroll_based_on.py
@@ -0,0 +1,6 @@
+from __future__ import unicode_literals
+import frappe
+
+def execute():
+	frappe.reload_doc("hr", "doctype", "hr_settings")
+	frappe.db.set_value("HR Settings", None, "payroll_based_on", "Leave")
\ No newline at end of file
diff --git a/erpnext/patches/v12_0/set_total_batch_quantity.py b/erpnext/patches/v12_0/set_total_batch_quantity.py
index d373275..7296eaa 100644
--- a/erpnext/patches/v12_0/set_total_batch_quantity.py
+++ b/erpnext/patches/v12_0/set_total_batch_quantity.py
@@ -6,6 +6,6 @@
 
 	for batch in frappe.get_all("Batch", fields=["name", "batch_id"]):
 		batch_qty = frappe.db.get_value("Stock Ledger Entry",
-			{"docstatus": 1, "batch_no": batch.batch_id, "is_cancelled": "No"},
+			{"docstatus": 1, "batch_no": batch.batch_id, "is_cancelled": 0},
 			"sum(actual_qty)") or 0.0
 		frappe.db.set_value("Batch", batch.name, "batch_qty", batch_qty, update_modified=False)
diff --git a/erpnext/patches/v12_0/update_appointment_reminder_scheduler_entry.py b/erpnext/patches/v12_0/update_appointment_reminder_scheduler_entry.py
new file mode 100644
index 0000000..91931ee
--- /dev/null
+++ b/erpnext/patches/v12_0/update_appointment_reminder_scheduler_entry.py
@@ -0,0 +1,7 @@
+import frappe
+
+def execute():
+	job = frappe.db.exists('Scheduled Job Type', 'patient_appointment.send_appointment_reminder')
+	if job:
+		method = 'erpnext.healthcare.doctype.patient_appointment.patient_appointment.send_appointment_reminder'
+		frappe.db.set_value('Scheduled Job Type', job, 'method', method)
\ No newline at end of file
diff --git a/erpnext/patches/v12_0/update_end_date_and_status_in_email_campaign.py b/erpnext/patches/v12_0/update_end_date_and_status_in_email_campaign.py
new file mode 100644
index 0000000..db71a73
--- /dev/null
+++ b/erpnext/patches/v12_0/update_end_date_and_status_in_email_campaign.py
@@ -0,0 +1,24 @@
+from __future__ import unicode_literals
+import frappe
+from frappe.utils import add_days, getdate, today
+
+def execute():
+    if frappe.db.exists('DocType', 'Email Campaign'):
+        email_campaign = frappe.get_all('Email Campaign')
+        for campaign in email_campaign:
+            doc = frappe.get_doc("Email Campaign",campaign["name"])
+            send_after_days = []
+
+            camp = frappe.get_doc("Campaign", doc.campaign_name)
+            for entry in camp.get("campaign_schedules"):
+                send_after_days.append(entry.send_after_days)
+            if send_after_days:
+                end_date = add_days(getdate(doc.start_date), max(send_after_days))
+                doc.db_set("end_date", end_date)
+            today_date = getdate(today())
+            if doc.start_date > today_date:
+                doc.db_set("status", "Scheduled")
+            elif end_date >= today_date:
+                doc.db_set("status", "In Progress")
+            elif end_date < today_date:
+                doc.db_set("status", "Completed") 
\ No newline at end of file
diff --git a/erpnext/patches/v12_0/update_is_cancelled_field.py b/erpnext/patches/v12_0/update_is_cancelled_field.py
new file mode 100644
index 0000000..0b2e827
--- /dev/null
+++ b/erpnext/patches/v12_0/update_is_cancelled_field.py
@@ -0,0 +1,15 @@
+from __future__ import unicode_literals
+import frappe
+
+def execute():
+	try:
+		frappe.db.sql("UPDATE `tabStock Ledger Entry` SET is_cancelled = 0 where is_cancelled in ('', NULL, 'No')")
+		frappe.db.sql("UPDATE `tabSerial No` SET is_cancelled = 0 where is_cancelled in ('', NULL, 'No')")
+
+		frappe.db.sql("UPDATE `tabStock Ledger Entry` SET is_cancelled = 1 where is_cancelled = 'Yes'")
+		frappe.db.sql("UPDATE `tabSerial No` SET is_cancelled = 1 where is_cancelled = 'Yes'")
+
+		frappe.reload_doc("stock", "doctype", "stock_ledger_entry")
+		frappe.reload_doc("stock", "doctype", "serial_no")
+	except:
+		pass
\ No newline at end of file
diff --git a/erpnext/education/doctype/video/__init__.py b/erpnext/patches/v13_0/__init__.py
similarity index 100%
rename from erpnext/education/doctype/video/__init__.py
rename to erpnext/patches/v13_0/__init__.py
diff --git a/erpnext/patches/v13_0/move_tax_slabs_from_payroll_period_to_income_tax_slab.py b/erpnext/patches/v13_0/move_tax_slabs_from_payroll_period_to_income_tax_slab.py
new file mode 100644
index 0000000..179be2c
--- /dev/null
+++ b/erpnext/patches/v13_0/move_tax_slabs_from_payroll_period_to_income_tax_slab.py
@@ -0,0 +1,99 @@
+# Copyright (c) 2019, Frappe and Contributors
+# License: GNU General Public License v3. See license.txt
+
+from __future__ import unicode_literals
+
+import frappe
+from frappe.model.utils.rename_field import rename_field
+
+def execute():
+	if not frappe.db.table_exists("Payroll Period"):
+		return
+
+	for doctype in ("income_tax_slab", "salary_structure_assignment", "employee_other_income", "income_tax_slab_other_charges"):
+		frappe.reload_doc("hr", "doctype", doctype)
+
+
+	for company in frappe.get_all("Company"):
+		payroll_periods =  frappe.db.sql("""
+			SELECT
+				name, start_date, end_date, standard_tax_exemption_amount
+			FROM
+				`tabPayroll Period`
+			WHERE company=%s
+			ORDER BY start_date DESC
+		""", company.name, as_dict = 1)
+			
+		for i, period in enumerate(payroll_periods):
+			income_tax_slab = frappe.new_doc("Income Tax Slab")
+			income_tax_slab.name = "Tax Slab:" + period.name
+
+			if i == 0:
+				income_tax_slab.disabled = 0
+			else:
+				income_tax_slab.disabled = 1
+
+			income_tax_slab.effective_from = period.start_date
+			income_tax_slab.company = company.name
+			income_tax_slab.allow_tax_exemption = 1
+			income_tax_slab.standard_tax_exemption_amount = period.standard_tax_exemption_amount
+
+			income_tax_slab.flags.ignore_mandatory = True
+			income_tax_slab.submit()
+
+			frappe.db.sql(
+			""" UPDATE `tabTaxable Salary Slab`
+				SET parent = %s , parentfield = 'slabs' , parenttype = "Income Tax Slab"
+				WHERE parent = %s
+			""", (income_tax_slab.name, period.name), as_dict = 1)
+
+			if i == 0:
+				frappe.db.sql("""
+					UPDATE
+						`tabSalary Structure Assignment`
+					set
+						income_tax_slab = %s
+					where
+						company = %s
+						and from_date >= %s
+						and docstatus < 2
+				""", (income_tax_slab.name, company.name, period.start_date))
+
+	# move other incomes to separate document
+	migrated = []
+	proofs = frappe.get_all("Employee Tax Exemption Proof Submission",
+		filters = {'docstatus': 1},
+		fields =['payroll_period', 'employee', 'company', 'income_from_other_sources']
+	)
+	for proof in proofs:
+		if proof.income_from_other_sources:
+			employee_other_income = frappe.new_doc("Employee Other Income")
+			employee_other_income.employee = proof.employee
+			employee_other_income.payroll_period = proof.payroll_period
+			employee_other_income.company = proof.company
+			employee_other_income.amount = proof.income_from_other_sources
+
+			try:
+				employee_other_income.submit()
+				migrated.append([proof.employee, proof.payroll_period])
+			except:
+				pass
+
+	declerations = frappe.get_all("Employee Tax Exemption Declaration",
+		filters = {'docstatus': 1},
+		fields =['payroll_period', 'employee', 'company', 'income_from_other_sources']
+	)
+
+	for declaration in declerations:
+		if declaration.income_from_other_sources \
+				and [declaration.employee, declaration.payroll_period] not in migrated:
+			employee_other_income = frappe.new_doc("Employee Other Income")
+			employee_other_income.employee = declaration.employee
+			employee_other_income.payroll_period = declaration.payroll_period
+			employee_other_income.company = declaration.company
+			employee_other_income.amount = declaration.income_from_other_sources
+
+			try:
+				employee_other_income.submit()
+			except:
+				pass
diff --git a/erpnext/patches/v4_2/fix_gl_entries_for_stock_transactions.py b/erpnext/patches/v4_2/fix_gl_entries_for_stock_transactions.py
index 16932af..c6c94d4 100644
--- a/erpnext/patches/v4_2/fix_gl_entries_for_stock_transactions.py
+++ b/erpnext/patches/v4_2/fix_gl_entries_for_stock_transactions.py
@@ -8,7 +8,7 @@
 def execute():
 	from erpnext.stock.stock_balance import repost
 	repost(allow_zero_rate=True, only_actual=True)
-	
+
 	frappe.reload_doctype("Account")
 
 	warehouse_account = frappe.db.sql("""select name, master_name from tabAccount
@@ -43,7 +43,7 @@
 						where voucher_type=%s and voucher_no=%s""", (voucher_type, voucher_no))
 
 					voucher = frappe.get_doc(voucher_type, voucher_no)
-					voucher.make_gl_entries(repost_future_gle=False)
+					voucher.make_gl_entries()
 					frappe.db.commit()
 				except Exception as e:
 					print(frappe.get_traceback())
diff --git a/erpnext/patches/v6_24/repost_valuation_rate_for_serialized_items.py b/erpnext/patches/v6_24/repost_valuation_rate_for_serialized_items.py
deleted file mode 100644
index 3b157a3..0000000
--- a/erpnext/patches/v6_24/repost_valuation_rate_for_serialized_items.py
+++ /dev/null
@@ -1,28 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-from frappe.utils import today
-from erpnext.accounts.utils import get_fiscal_year
-from erpnext.stock.stock_ledger import update_entries_after
-
-def execute():
-	try:
-		year_start_date = get_fiscal_year(today())[1]
-	except:
-		return
-	
-	if year_start_date:
-		items = frappe.db.sql("""select distinct item_code, warehouse from `tabStock Ledger Entry` 
-			where ifnull(serial_no, '') != '' and actual_qty > 0 and incoming_rate=0""", as_dict=1)
-		
-		for d in items:
-			try:
-				update_entries_after({
-					"item_code": d.item_code, 
-					"warehouse": d.warehouse,
-					"posting_date": year_start_date
-				}, allow_zero_rate=True)
-			except:
-				pass
\ No newline at end of file
diff --git a/erpnext/patches/v7_0/repost_future_gle_for_purchase_invoice.py b/erpnext/patches/v7_0/repost_future_gle_for_purchase_invoice.py
deleted file mode 100644
index 9e21fb6..0000000
--- a/erpnext/patches/v7_0/repost_future_gle_for_purchase_invoice.py
+++ /dev/null
@@ -1,24 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-from frappe.utils import cint
-from erpnext.stock import get_warehouse_account_map
-from erpnext.controllers.stock_controller import update_gl_entries_after
-
-def execute():
-	company_list = frappe.db.sql_list("""Select name from tabCompany where enable_perpetual_inventory = 1""")
-	frappe.reload_doc('accounts', 'doctype', 'sales_invoice')
-
-	frappe.reload_doctype("Purchase Invoice")
-	wh_account = get_warehouse_account_map()
-
-	for pi in frappe.get_all("Purchase Invoice", fields=["name", "company"], filters={"docstatus": 1, "update_stock": 1}):
-		if pi.company in company_list:
-			pi_doc = frappe.get_doc("Purchase Invoice", pi.name)
-			items, warehouses = pi_doc.get_items_and_warehouses()
-			update_gl_entries_after(pi_doc.posting_date, pi_doc.posting_time,
-				warehouses, items, wh_account, company = pi.company)
-
-			frappe.db.commit()
\ No newline at end of file
diff --git a/erpnext/patches/v7_0/repost_gle_for_pi_with_update_stock.py b/erpnext/patches/v7_0/repost_gle_for_pi_with_update_stock.py
index 2d1a151..b864e59 100644
--- a/erpnext/patches/v7_0/repost_gle_for_pi_with_update_stock.py
+++ b/erpnext/patches/v7_0/repost_gle_for_pi_with_update_stock.py
@@ -8,13 +8,13 @@
 def execute():
 	frappe.reload_doctype("Purchase Invoice")
 
-	for pi in frappe.db.sql("""select name from `tabPurchase Invoice` 
-		where company in(select name from tabCompany where enable_perpetual_inventory = 1) and 
+	for pi in frappe.db.sql("""select name from `tabPurchase Invoice`
+		where company in(select name from tabCompany where enable_perpetual_inventory = 1) and
 		update_stock=1 and docstatus=1 order by posting_date asc""", as_dict=1):
-		
-			frappe.db.sql("""delete from `tabGL Entry` 
+
+			frappe.db.sql("""delete from `tabGL Entry`
 				where voucher_type = 'Purchase Invoice' and voucher_no = %s""", pi.name)
-				
+
 			pi_doc = frappe.get_doc("Purchase Invoice", pi.name)
-			pi_doc.make_gl_entries(repost_future_gle=False)
+			pi_doc.make_gl_entries()
 			frappe.db.commit()
\ No newline at end of file
diff --git a/erpnext/projects/doctype/project_template/project_template.json b/erpnext/projects/doctype/project_template/project_template.json
index 8352995..445ad9f 100644
--- a/erpnext/projects/doctype/project_template/project_template.json
+++ b/erpnext/projects/doctype/project_template/project_template.json
@@ -1,130 +1,52 @@
 {
- "allow_copy": 0,
- "allow_events_in_timeline": 0,
- "allow_guest_to_view": 0,
- "allow_import": 0,
- "allow_rename": 0,
+ "actions": [],
  "autoname": "Prompt",
- "beta": 0,
  "creation": "2019-02-18 17:23:11.708371",
- "custom": 0,
- "docstatus": 0,
  "doctype": "DocType",
- "document_type": "",
  "editable_grid": 1,
  "engine": "InnoDB",
+ "field_order": [
+  "project_type",
+  "tasks"
+ ],
  "fields": [
   {
-   "allow_bulk_edit": 0,
-   "allow_in_quick_entry": 0,
-   "allow_on_submit": 0,
-   "bold": 0,
-   "collapsible": 0,
-   "columns": 0,
    "fieldname": "project_type",
    "fieldtype": "Link",
-   "hidden": 0,
-   "ignore_user_permissions": 0,
-   "ignore_xss_filter": 0,
-   "in_filter": 0,
-   "in_global_search": 0,
    "in_list_view": 1,
-   "in_standard_filter": 0,
    "label": "Project Type",
-   "length": 0,
-   "no_copy": 0,
-   "options": "Project Type",
-   "permlevel": 0,
-   "precision": "",
-   "print_hide": 0,
-   "print_hide_if_no_value": 0,
-   "read_only": 0,
-   "remember_last_selected_value": 0,
-   "report_hide": 0,
-   "reqd": 0,
-   "search_index": 0,
-   "set_only_once": 0,
-   "translatable": 0,
-   "unique": 0
+   "options": "Project Type"
   },
   {
-   "allow_bulk_edit": 0,
-   "allow_in_quick_entry": 0,
-   "allow_on_submit": 0,
-   "bold": 0,
-   "collapsible": 0,
-   "columns": 0,
    "fieldname": "tasks",
    "fieldtype": "Table",
-   "hidden": 0,
-   "ignore_user_permissions": 0,
-   "ignore_xss_filter": 0,
-   "in_filter": 0,
-   "in_global_search": 0,
-   "in_list_view": 0,
-   "in_standard_filter": 0,
    "label": "Tasks",
-   "length": 0,
-   "no_copy": 0,
    "options": "Project Template Task",
-   "permlevel": 0,
-   "precision": "",
-   "print_hide": 0,
-   "print_hide_if_no_value": 0,
-   "read_only": 0,
-   "remember_last_selected_value": 0,
-   "report_hide": 0,
-   "reqd": 1,
-   "search_index": 0,
-   "set_only_once": 0,
-   "translatable": 0,
-   "unique": 0
+   "reqd": 1
   }
  ],
- "has_web_view": 0,
- "hide_heading": 0,
- "hide_toolbar": 0,
- "idx": 0,
- "image_view": 0,
- "in_create": 0,
- "is_submittable": 0,
- "issingle": 0,
- "istable": 0,
- "max_attachments": 0,
- "modified": "2019-02-18 18:01:26.519832",
+ "links": [],
+ "modified": "2020-04-26 02:23:53.990322",
  "modified_by": "Administrator",
  "module": "Projects",
  "name": "Project Template",
- "name_case": "",
  "owner": "Administrator",
  "permissions": [
   {
-   "amend": 0,
-   "cancel": 0,
    "create": 1,
    "delete": 1,
    "email": 1,
    "export": 1,
-   "if_owner": 0,
-   "import": 0,
-   "permlevel": 0,
    "print": 1,
    "read": 1,
    "report": 1,
    "role": "System Manager",
-   "set_user_permissions": 0,
    "share": 1,
-   "submit": 0,
    "write": 1
   }
  ],
  "quick_entry": 1,
- "read_only": 0,
- "read_only_onload": 0,
- "show_name_in_global_search": 0,
  "sort_field": "modified",
  "sort_order": "DESC",
- "track_changes": 1,
- "track_seen": 0,
- "track_views": 0
+ "track_changes": 1
 }
\ No newline at end of file
diff --git a/erpnext/public/js/controllers/stock_controller.js b/erpnext/public/js/controllers/stock_controller.js
index 1c12c35..2ce49e7 100644
--- a/erpnext/public/js/controllers/stock_controller.js
+++ b/erpnext/public/js/controllers/stock_controller.js
@@ -50,7 +50,7 @@
 
 	show_stock_ledger: function() {
 		var me = this;
-		if(this.frm.doc.docstatus===1) {
+		if(this.frm.doc.docstatus > 0) {
 			cur_frm.add_custom_button(__("Stock Ledger"), function() {
 				frappe.route_options = {
 					voucher_no: me.frm.doc.name,
@@ -66,7 +66,7 @@
 
 	show_general_ledger: function() {
 		var me = this;
-		if(this.frm.doc.docstatus===1) {
+		if(this.frm.doc.docstatus > 0) {
 			cur_frm.add_custom_button(__('Accounting Ledger'), function() {
 				frappe.route_options = {
 					voucher_no: me.frm.doc.name,
diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js
index bbc2d69..28c2102 100644
--- a/erpnext/public/js/controllers/transaction.js
+++ b/erpnext/public/js/controllers/transaction.js
@@ -175,6 +175,20 @@
 			};
 		}
 
+		if (this.frm.fields_dict["items"].grid.get_field('blanket_order')) {
+			this.frm.set_query("blanket_order", "items", function(doc, cdt, cdn) {
+				var item = locals[cdt][cdn];
+				return {
+					query: "erpnext.controllers.queries.get_blanket_orders",
+					filters: {
+						"company": doc.company,
+						"blanket_order_type": doc.doctype === "Sales Order" ? "Selling" : "Purchasing",
+						"item": item.item_code
+					}
+				}
+			});
+		}
+
 	},
 	onload: function() {
 		var me = this;
@@ -288,7 +302,7 @@
 		this.setup_sms();
 		this.setup_quality_inspection();
 		let scan_barcode_field = this.frm.get_field('scan_barcode');
-		if (scan_barcode_field) {
+		if (scan_barcode_field && scan_barcode_field.get_value()) {
 			scan_barcode_field.set_value("");
 			scan_barcode_field.set_new_description("");
 
@@ -1412,7 +1426,7 @@
 				me.frm.doc.items.forEach(d => {
 					if (in_list(data.apply_rule_on_other_items, d[data.apply_rule_on])) {
 						for(var k in data) {
-							if (in_list(fields, k) && data[k]) {
+							if (in_list(fields, k) && data[k] && (data.price_or_product_discount === 'price' || k === 'pricing_rules')) {
 								frappe.model.set_value(d.doctype, d.name, k, data[k]);
 							}
 						}
diff --git a/erpnext/public/js/utils/dimension_tree_filter.js b/erpnext/public/js/utils/dimension_tree_filter.js
index 75c5a82..b223fc5 100644
--- a/erpnext/public/js/utils/dimension_tree_filter.js
+++ b/erpnext/public/js/utils/dimension_tree_filter.js
@@ -24,7 +24,7 @@
 		onload: function(frm) {
 			erpnext.dimension_filters.forEach((dimension) => {
 				frappe.model.with_doctype(dimension['document_type'], () => {
-					if (frappe.meta.has_field(dimension['document_type'], 'is_group')) {
+					if(frappe.meta.has_field(dimension['document_type'], 'is_group')) {
 						frm.set_query(dimension['fieldname'], {
 							"is_group": 0
 						});
@@ -42,19 +42,21 @@
 
 		update_dimension: function(frm) {
 			erpnext.dimension_filters.forEach((dimension) => {
-				if (frm.is_new()) {
-					if (frm.doc.company && Object.keys(default_dimensions || {}).length > 0
+				if(frm.is_new()) {
+					if(frm.doc.company && Object.keys(default_dimensions || {}).length > 0
 						&& default_dimensions[frm.doc.company]) {
 
-						if (frappe.meta.has_field(doctype, dimension['fieldname'])) {
-							frm.set_value(dimension['fieldname'],
-								default_dimensions[frm.doc.company][dimension['document_type']]);
-						}
+						let default_dimension = default_dimensions[frm.doc.company][dimension['document_type']];
 
-						$.each(frm.doc.items || frm.doc.accounts || [], function(i, row) {
-							frappe.model.set_value(row.doctype, row.name, dimension['fieldname'],
-								default_dimensions[frm.doc.company][dimension['document_type']])
-						});
+						if(default_dimension) {
+							if (frappe.meta.has_field(doctype, dimension['fieldname'])) {
+								frm.set_value(dimension['fieldname'], default_dimension);
+							}
+
+							$.each(frm.doc.items || frm.doc.accounts || [], function(i, row) {
+								frappe.model.set_value(row.doctype, row.name, dimension['fieldname'], default_dimension);
+							});
+						}
 					}
 				}
 			});
@@ -76,20 +78,6 @@
 				var row = frappe.get_doc(cdt, cdn);
 				frm.script_manager.copy_from_first_row("accounts", row, [dimension['fieldname']]);
 			});
-		},
-
-		items_add: function(frm, cdt, cdn) {
-			erpnext.dimension_filters.forEach((dimension) => {
-				var row = frappe.get_doc(cdt, cdn);
-				frm.script_manager.copy_from_first_row("items", row, [dimension['fieldname']]);
-			});
-		},
-
-		accounts_add: function(frm, cdt, cdn) {
-			erpnext.dimension_filters.forEach((dimension) => {
-				var row = frappe.get_doc(cdt, cdn);
-				frm.script_manager.copy_from_first_row("accounts", row, [dimension['fieldname']]);
-			});
 		}
 	});
 });
\ No newline at end of file
diff --git a/erpnext/regional/doctype/datev_settings/datev_settings.json b/erpnext/regional/doctype/datev_settings/datev_settings.json
index 6860ed3..39486df 100644
--- a/erpnext/regional/doctype/datev_settings/datev_settings.json
+++ b/erpnext/regional/doctype/datev_settings/datev_settings.json
@@ -28,7 +28,8 @@
    "fieldtype": "Data",
    "in_list_view": 1,
    "label": "Client ID",
-   "reqd": 1
+   "reqd": 1,
+   "length": 5
   },
   {
    "fieldname": "consultant",
@@ -42,7 +43,8 @@
    "fieldtype": "Data",
    "in_list_view": 1,
    "label": "Consultant ID",
-   "reqd": 1
+   "reqd": 1,
+   "length": 7
   },
   {
    "fieldname": "column_break_2",
@@ -102,4 +104,4 @@
  "sort_field": "modified",
  "sort_order": "DESC",
  "track_changes": 1
-}
\ No newline at end of file
+}
diff --git a/erpnext/accounts/doctype/account_subtype/__init__.py b/erpnext/regional/doctype/lower_deduction_certificate/__init__.py
similarity index 100%
copy from erpnext/accounts/doctype/account_subtype/__init__.py
copy to erpnext/regional/doctype/lower_deduction_certificate/__init__.py
diff --git a/erpnext/regional/doctype/lower_deduction_certificate/lower_deduction_certificate.js b/erpnext/regional/doctype/lower_deduction_certificate/lower_deduction_certificate.js
new file mode 100644
index 0000000..8257bf8
--- /dev/null
+++ b/erpnext/regional/doctype/lower_deduction_certificate/lower_deduction_certificate.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('Lower Deduction Certificate', {
+	// refresh: function(frm) {
+
+	// }
+});
diff --git a/erpnext/regional/doctype/lower_deduction_certificate/lower_deduction_certificate.json b/erpnext/regional/doctype/lower_deduction_certificate/lower_deduction_certificate.json
new file mode 100644
index 0000000..f48fe6f
--- /dev/null
+++ b/erpnext/regional/doctype/lower_deduction_certificate/lower_deduction_certificate.json
@@ -0,0 +1,138 @@
+{
+ "actions": [],
+ "autoname": "field:certificate_no",
+ "creation": "2020-03-10 23:12:10.072631",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "certificate_details_section",
+  "section_code",
+  "fiscal_year",
+  "column_break_3",
+  "certificate_no",
+  "section_break_3",
+  "supplier",
+  "column_break_7",
+  "pan_no",
+  "validity_details_section",
+  "valid_from",
+  "column_break_10",
+  "valid_upto",
+  "section_break_9",
+  "rate",
+  "column_break_14",
+  "certificate_limit"
+ ],
+ "fields": [
+  {
+   "fieldname": "certificate_no",
+   "fieldtype": "Data",
+   "in_list_view": 1,
+   "label": "Certificate No",
+   "reqd": 1,
+   "unique": 1
+  },
+  {
+   "fieldname": "section_code",
+   "fieldtype": "Select",
+   "label": "Section Code",
+   "options": "192\n193\n194\n194A\n194C\n194D\n194H\n194I\n194J\n194LA\n194LBB\n194LBC\n195",
+   "reqd": 1
+  },
+  {
+   "fieldname": "section_break_3",
+   "fieldtype": "Section Break",
+   "label": "Deductee Details"
+  },
+  {
+   "fieldname": "supplier",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "label": "Supplier",
+   "options": "Supplier",
+   "reqd": 1
+  },
+  {
+   "fetch_from": "supplier.pan",
+   "fetch_if_empty": 1,
+   "fieldname": "pan_no",
+   "fieldtype": "Data",
+   "in_list_view": 1,
+   "label": "PAN No",
+   "reqd": 1
+  },
+  {
+   "fieldname": "validity_details_section",
+   "fieldtype": "Section Break",
+   "label": "Validity Details"
+  },
+  {
+   "fieldname": "valid_upto",
+   "fieldtype": "Date",
+   "label": "Valid Upto",
+   "reqd": 1
+  },
+  {
+   "fieldname": "section_break_9",
+   "fieldtype": "Section Break"
+  },
+  {
+   "fieldname": "rate",
+   "fieldtype": "Percent",
+   "label": "Rate Of TDS As Per Certificate",
+   "reqd": 1
+  },
+  {
+   "fieldname": "certificate_limit",
+   "fieldtype": "Currency",
+   "label": "Certificate Limit",
+   "reqd": 1
+  },
+  {
+   "fieldname": "certificate_details_section",
+   "fieldtype": "Section Break",
+   "label": "Certificate Details"
+  },
+  {
+   "fieldname": "column_break_3",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "column_break_10",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "column_break_14",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "column_break_7",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "valid_from",
+   "fieldtype": "Date",
+   "in_list_view": 1,
+   "label": "Valid From",
+   "reqd": 1
+  },
+  {
+   "fieldname": "fiscal_year",
+   "fieldtype": "Link",
+   "label": "Fiscal Year",
+   "options": "Fiscal Year",
+   "reqd": 1
+  }
+ ],
+ "links": [],
+ "modified": "2020-04-23 23:04:41.203721",
+ "modified_by": "Administrator",
+ "module": "Regional",
+ "name": "Lower Deduction Certificate",
+ "owner": "Administrator",
+ "permissions": [],
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/regional/doctype/lower_deduction_certificate/lower_deduction_certificate.py b/erpnext/regional/doctype/lower_deduction_certificate/lower_deduction_certificate.py
new file mode 100644
index 0000000..e8a8ed8
--- /dev/null
+++ b/erpnext/regional/doctype/lower_deduction_certificate/lower_deduction_certificate.py
@@ -0,0 +1,26 @@
+# -*- 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 getdate
+from frappe.model.document import Document
+from erpnext.accounts.utils import get_fiscal_year
+
+class LowerDeductionCertificate(Document):
+	def validate(self):
+		if getdate(self.valid_upto) < getdate(self.valid_from):
+			frappe.throw(_("Valid Upto date cannot be before Valid From date"))
+
+		fiscal_year = get_fiscal_year(fiscal_year=self.fiscal_year, as_dict=True)
+
+		if not (fiscal_year.year_start_date <= getdate(self.valid_from) \
+			<= fiscal_year.year_end_date):
+			frappe.throw(_("Valid From date not in Fiscal Year {0}").format(frappe.bold(self.fiscal_year)))
+
+		if not (fiscal_year.year_start_date <= getdate(self.valid_upto) \
+			<= fiscal_year.year_end_date):
+			frappe.throw(_("Valid Upto date not in Fiscal Year {0}").format(frappe.bold(self.fiscal_year)))
+
diff --git a/erpnext/regional/doctype/lower_deduction_certificate/test_lower_deduction_certificate.py b/erpnext/regional/doctype/lower_deduction_certificate/test_lower_deduction_certificate.py
new file mode 100644
index 0000000..7e95020
--- /dev/null
+++ b/erpnext/regional/doctype/lower_deduction_certificate/test_lower_deduction_certificate.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 TestLowerDeductionCertificate(unittest.TestCase):
+	pass
diff --git a/erpnext/regional/india/setup.py b/erpnext/regional/india/setup.py
index 4be6804..8593966 100644
--- a/erpnext/regional/india/setup.py
+++ b/erpnext/regional/india/setup.py
@@ -61,7 +61,7 @@
 			)).insert()
 
 def add_permissions():
-	for doctype in ('GST HSN Code', 'GST Settings', 'GSTR 3B Report'):
+	for doctype in ('GST HSN Code', 'GST Settings', 'GSTR 3B Report', 'Lower Deduction Certificate'):
 		add_permission(doctype, 'All', 0)
 		for role in ('Accounts Manager', 'Accounts User', 'System Manager'):
 			add_permission(doctype, role, 0)
@@ -531,12 +531,18 @@
 
 def set_salary_components(docs):
 	docs.extend([
-		{'doctype': 'Salary Component', 'salary_component': 'Professional Tax', 'description': 'Professional Tax', 'type': 'Deduction'},
-		{'doctype': 'Salary Component', 'salary_component': 'Provident Fund', 'description': 'Provident fund', 'type': 'Deduction'},
-		{'doctype': 'Salary Component', 'salary_component': 'House Rent Allowance', 'description': 'House Rent Allowance', 'type': 'Earning'},
-		{'doctype': 'Salary Component', 'salary_component': 'Basic', 'description': 'Basic', 'type': 'Earning'},
-		{'doctype': 'Salary Component', 'salary_component': 'Arrear', 'description': 'Arrear', 'type': 'Earning'},
-		{'doctype': 'Salary Component', 'salary_component': 'Leave Encashment', 'description': 'Leave Encashment', 'type': 'Earning'}
+		{'doctype': 'Salary Component', 'salary_component': 'Professional Tax',
+			'description': 'Professional Tax', 'type': 'Deduction', 'exempted_from_income_tax': 1},
+		{'doctype': 'Salary Component', 'salary_component': 'Provident Fund',
+			'description': 'Provident fund', 'type': 'Deduction', 'is_tax_applicable': 1},
+		{'doctype': 'Salary Component', 'salary_component': 'House Rent Allowance',
+			'description': 'House Rent Allowance', 'type': 'Earning', 'is_tax_applicable': 1},
+		{'doctype': 'Salary Component', 'salary_component': 'Basic',
+			'description': 'Basic', 'type': 'Earning', 'is_tax_applicable': 1},
+		{'doctype': 'Salary Component', 'salary_component': 'Arrear',
+			'description': 'Arrear', 'type': 'Earning', 'is_tax_applicable': 1},
+		{'doctype': 'Salary Component', 'salary_component': 'Leave Encashment',
+			'description': 'Leave Encashment', 'type': 'Earning', 'is_tax_applicable': 1}
 	])
 
 def set_tax_withholding_category(company):
diff --git a/erpnext/regional/india/utils.py b/erpnext/regional/india/utils.py
index 0282382..3309858 100644
--- a/erpnext/regional/india/utils.py
+++ b/erpnext/regional/india/utils.py
@@ -288,7 +288,7 @@
 	})
 
 def get_component_amt_from_salary_slip(employee, salary_structure, basic_component, hra_component):
-	salary_slip = make_salary_slip(salary_structure, employee=employee, for_preview=1)
+	salary_slip = make_salary_slip(salary_structure, employee=employee, for_preview=1, ignore_permissions=True)
 	basic_amt, hra_amt = 0, 0
 	for earning in salary_slip.earnings:
 		if earning.salary_component == basic_component:
@@ -372,7 +372,6 @@
 		return exemptions
 
 def get_ewb_data(dt, dn):
-	dn = dn.split(',')
 
 	ewaybills = []
 	for doc_name in dn:
@@ -453,16 +452,22 @@
 
 @frappe.whitelist()
 def generate_ewb_json(dt, dn):
+	dn = json.loads(dn)
+	return get_ewb_data(dt, dn)
 
-	data = get_ewb_data(dt, dn)
+@frappe.whitelist()
+def download_ewb_json():
+	data = frappe._dict(frappe.local.form_dict)
 
-	frappe.local.response.filecontent = json.dumps(data, indent=4, sort_keys=True)
+	frappe.local.response.filecontent = json.dumps(data['data'], indent=4, sort_keys=True)
 	frappe.local.response.type = 'download'
 
-	if len(data['billLists']) > 1:
+	billList = json.loads(data['data'])['billLists']
+
+	if len(billList) > 1:
 		doc_name = 'Bulk'
 	else:
-		doc_name = dn
+		doc_name = data['docname']
 
 	frappe.local.response.filename = '{0}_e-WayBill_Data_{1}.json'.format(doc_name, frappe.utils.random_string(5))
 
diff --git a/erpnext/selling/desk_page/retail/retail.json b/erpnext/selling/desk_page/retail/retail.json
index 9f3912d..7b30af2 100644
--- a/erpnext/selling/desk_page/retail/retail.json
+++ b/erpnext/selling/desk_page/retail/retail.json
@@ -17,7 +17,7 @@
  "idx": 0,
  "is_standard": 1,
  "label": "Retail",
- "modified": "2020-04-01 11:28:50.966145",
+ "modified": "2020-04-26 22:42:39.346750",
  "modified_by": "Administrator",
  "module": "Selling",
  "name": "Retail",
diff --git a/erpnext/selling/doctype/campaign/campaign_dashboard.py b/erpnext/selling/doctype/campaign/campaign_dashboard.py
index a9d8eca..3cef560 100644
--- a/erpnext/selling/doctype/campaign/campaign_dashboard.py
+++ b/erpnext/selling/doctype/campaign/campaign_dashboard.py
@@ -8,6 +8,10 @@
 			{
 				'label': _('Email Campaigns'),
 				'items': ['Email Campaign']
+			},
+			{
+				'label': _('Social Media Campaigns'),
+				'items': ['Social Media Post']
 			}
-		],
+		]
 	}
diff --git a/erpnext/selling/doctype/customer/customer_dashboard.py b/erpnext/selling/doctype/customer/customer_dashboard.py
index 654dd48..22e30e3 100644
--- a/erpnext/selling/doctype/customer/customer_dashboard.py
+++ b/erpnext/selling/doctype/customer/customer_dashboard.py
@@ -11,7 +11,8 @@
 		'non_standard_fieldnames': {
 			'Payment Entry': 'party',
 			'Quotation': 'party_name',
-			'Opportunity': 'party_name'
+			'Opportunity': 'party_name',
+			'Bank Account': 'party'
 		},
 		'dynamic_links': {
 			'party_name': ['Customer', 'quotation_to']
@@ -27,7 +28,7 @@
 			},
 			{
 				'label': _('Payments'),
-				'items': ['Payment Entry']
+				'items': ['Payment Entry', 'Bank Account']
 			},
 			{
 				'label': _('Support'),
diff --git a/erpnext/selling/doctype/quotation/quotation.py b/erpnext/selling/doctype/quotation/quotation.py
index 7c47b8a..7cfec5a 100644
--- a/erpnext/selling/doctype/quotation/quotation.py
+++ b/erpnext/selling/doctype/quotation/quotation.py
@@ -193,12 +193,23 @@
 	return doclist
 
 def set_expired_status():
-	frappe.db.sql("""
-		UPDATE
-			`tabQuotation` SET `status` = 'Expired'
-		WHERE
-			`status` not in ('Ordered', 'Expired', 'Lost', 'Cancelled') AND `valid_till` < %s
-		""", (nowdate()))
+	# filter out submitted non expired quotations whose validity has been ended
+	cond = "qo.docstatus = 1 and qo.status != 'Expired' and qo.valid_till < %s"
+	# check if those QUO have SO against it
+	so_against_quo = """
+		SELECT 
+			so.name FROM `tabSales Order` so, `tabSales Order Item` so_item
+		WHERE 
+			so_item.docstatus = 1 and so.docstatus = 1
+			and so_item.parent = so.name
+			and so_item.prevdoc_docname = qo.name"""
+
+	# if not exists any SO, set status as Expired
+	frappe.db.sql(
+		"""UPDATE `tabQuotation` qo SET qo.status = 'Expired' WHERE {cond} and not exists({so_against_quo})"""
+			.format(cond=cond, so_against_quo=so_against_quo),
+			(nowdate())
+		)
 
 @frappe.whitelist()
 def make_sales_invoice(source_name, target_doc=None):
diff --git a/erpnext/selling/doctype/sales_order/sales_order.js b/erpnext/selling/doctype/sales_order/sales_order.js
index 61aa608..45a43c5 100644
--- a/erpnext/selling/doctype/sales_order/sales_order.js
+++ b/erpnext/selling/doctype/sales_order/sales_order.js
@@ -65,15 +65,6 @@
 			}
 		});
 
-		frm.set_query("blanket_order", "items", function() {
-			return {
-				filters: {
-					"company": frm.doc.company,
-					"docstatus": 1
-				}
-			}
-		});
-
 		erpnext.queries.setup_warehouse_query(frm);
 	},
 
@@ -149,8 +140,13 @@
 
 					this.frm.add_custom_button(__('Pick List'), () => this.create_pick_list(), __('Create'));
 
+					const order_is_a_sale = ["Sales", "Shopping Cart"].indexOf(doc.order_type) !== -1;
+					const order_is_maintenance = ["Maintenance"].indexOf(doc.order_type) !== -1;
+					// order type has been customised then show all the action buttons
+					const order_is_a_custom_sale = ["Sales", "Shopping Cart", "Maintenance"].indexOf(doc.order_type) === -1;
+
 					// delivery note
-					if(flt(doc.per_delivered, 6) < 100 && ["Sales", "Shopping Cart"].indexOf(doc.order_type)!==-1 && allow_delivery) {
+					if(flt(doc.per_delivered, 6) < 100 && (order_is_a_sale || order_is_a_custom_sale) && allow_delivery) {
 						this.frm.add_custom_button(__('Delivery Note'), () => this.make_delivery_note_based_on_delivery_date(), __('Create'));
 						this.frm.add_custom_button(__('Work Order'), () => this.make_work_order(), __('Create'));
 					}
@@ -161,8 +157,7 @@
 					}
 
 					// material request
-					if(!doc.order_type || ["Sales", "Shopping Cart"].indexOf(doc.order_type)!==-1
-						&& flt(doc.per_delivered, 6) < 100) {
+					if(!doc.order_type || (order_is_a_sale || order_is_a_custom_sale) && flt(doc.per_delivered, 6) < 100) {
 						this.frm.add_custom_button(__('Material Request'), () => this.make_material_request(), __('Create'));
 						this.frm.add_custom_button(__('Request for Raw Materials'), () => this.make_raw_material_request(), __('Create'));
 					}
@@ -171,14 +166,13 @@
 						this.frm.add_custom_button(__('Purchase Order'), () => this.make_purchase_order(), __('Create'));
 
 					// maintenance
-					if(flt(doc.per_delivered, 2) < 100 &&
-							["Sales", "Shopping Cart"].indexOf(doc.order_type)===-1) {
+					if(flt(doc.per_delivered, 2) < 100 && (order_is_maintenance || order_is_a_custom_sale)) {
 						this.frm.add_custom_button(__('Maintenance Visit'), () => this.make_maintenance_visit(), __('Create'));
 						this.frm.add_custom_button(__('Maintenance Schedule'), () => this.make_maintenance_schedule(), __('Create'));
 					}
 
 					// project
-					if(flt(doc.per_delivered, 2) < 100 && ["Sales", "Shopping Cart"].indexOf(doc.order_type)!==-1 && allow_delivery) {
+					if(flt(doc.per_delivered, 2) < 100 && (order_is_a_sale || order_is_a_custom_sale) && allow_delivery) {
 							this.frm.add_custom_button(__('Project'), () => this.make_project(), __('Create'));
 					}
 
diff --git a/erpnext/selling/doctype/sales_order/test_sales_order.py b/erpnext/selling/doctype/sales_order/test_sales_order.py
index d8e9a63..b8b0d40 100644
--- a/erpnext/selling/doctype/sales_order/test_sales_order.py
+++ b/erpnext/selling/doctype/sales_order/test_sales_order.py
@@ -335,7 +335,7 @@
 		self.assertEqual(so.get("items")[-1].qty, 7)
 		self.assertEqual(so.get("items")[-1].amount, 1400)
 		self.assertEqual(so.status, 'To Deliver and Bill')
-	
+
 	def test_remove_item_in_update_child_qty_rate(self):
 		so = make_sales_order(**{
 			"item_list": [{
@@ -373,7 +373,7 @@
 			"docname": so.get("items")[0].name
 		}])
 		update_child_qty_rate('Sales Order', trans_item, so.name)
-		
+
 		so.reload()
 		self.assertEqual(len(so.get("items")), 1)
 		self.assertEqual(so.status, 'To Deliver and Bill')
@@ -760,10 +760,9 @@
 		self.assertEqual(reserved_serial_no, dn.get("items")[0].serial_no)
 		item_line = dn.get("items")[0]
 		item_line.serial_no = item_serial_no.name
-		self.assertRaises(frappe.ValidationError, dn.submit)
 		item_line = dn.get("items")[0]
 		item_line.serial_no =  reserved_serial_no
-		self.assertTrue(dn.submit)
+		dn.submit()
 		dn.load_from_db()
 		dn.cancel()
 		si = make_sales_invoice(so.name)
diff --git a/erpnext/selling/report/sales_partner_target_variance_based_on_item_group/item_group_wise_sales_target_variance.py b/erpnext/selling/report/sales_partner_target_variance_based_on_item_group/item_group_wise_sales_target_variance.py
index 0cb606b..857b982 100644
--- a/erpnext/selling/report/sales_partner_target_variance_based_on_item_group/item_group_wise_sales_target_variance.py
+++ b/erpnext/selling/report/sales_partner_target_variance_based_on_item_group/item_group_wise_sales_target_variance.py
@@ -11,8 +11,8 @@
 
 def get_data_column(filters, partner_doctype):
 	data = []
-	period_list = get_period_list(filters.fiscal_year, filters.fiscal_year,
-		filters.period, company=filters.company)
+	period_list = get_period_list(filters.fiscal_year, filters.fiscal_year, '', '',
+		'Fiscal Year', filters.period, company=filters.company)
 
 	rows = get_data(filters, period_list, partner_doctype)
 	columns = get_columns(filters, period_list, partner_doctype)
diff --git a/erpnext/setup/setup_wizard/operations/install_fixtures.py b/erpnext/setup/setup_wizard/operations/install_fixtures.py
index e4986e3..3be6f44 100644
--- a/erpnext/setup/setup_wizard/operations/install_fixtures.py
+++ b/erpnext/setup/setup_wizard/operations/install_fixtures.py
@@ -32,7 +32,7 @@
 		{ 'doctype': 'Domain', 'domain': 'Agriculture'},
 		{ 'doctype': 'Domain', 'domain': 'Non Profit'},
 
-		# ensure at least an empty Address Template exists for this Country	
+		# ensure at least an empty Address Template exists for this Country
 		{'doctype':"Address Template", "country": country},
 
 		# item group
@@ -271,7 +271,7 @@
 
 	# Records for the Supplier Scorecard
 	from erpnext.buying.doctype.supplier_scorecard.supplier_scorecard import make_default_records
-	
+
 	make_default_records()
 	make_records(records)
 	set_up_address_templates(default_country=country)
diff --git a/erpnext/stock/doctype/bin/bin.py b/erpnext/stock/doctype/bin/bin.py
index 73b36e3..7acdec7 100644
--- a/erpnext/stock/doctype/bin/bin.py
+++ b/erpnext/stock/doctype/bin/bin.py
@@ -23,22 +23,19 @@
 			if not args.get("posting_date"):
 				args["posting_date"] = nowdate()
 
-			# update valuation and qty after transaction for post dated entry
-			if args.get("is_cancelled") == "Yes" and via_landed_cost_voucher:
-				return
 			update_entries_after({
 				"item_code": self.item_code,
 				"warehouse": self.warehouse,
 				"posting_date": args.get("posting_date"),
 				"posting_time": args.get("posting_time"),
-				"voucher_no": args.get("voucher_no")
+				"voucher_no": args.get("voucher_no"),
+				"sle_id": args.sle_id
 			}, allow_negative_stock=allow_negative_stock, via_landed_cost_voucher=via_landed_cost_voucher)
 
 	def update_qty(self, args):
 		# update the stock values (for current quantities)
 		if args.get("voucher_type")=="Stock Reconciliation":
-			if args.get('is_cancelled') == 'No':
-				self.actual_qty = args.get("qty_after_transaction")
+			self.actual_qty = args.get("qty_after_transaction")
 		else:
 			self.actual_qty = flt(self.actual_qty) + flt(args.get("actual_qty"))
 
diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.js b/erpnext/stock/doctype/delivery_note/delivery_note.js
index c1ddf36..60f6a68 100644
--- a/erpnext/stock/doctype/delivery_note/delivery_note.js
+++ b/erpnext/stock/doctype/delivery_note/delivery_note.js
@@ -177,7 +177,7 @@
 			}
 		}
 
-		if (doc.docstatus==1) {
+		if (doc.docstatus > 0) {
 			this.show_stock_ledger();
 			if (erpnext.is_perpetual_inventory_enabled(doc.company)) {
 				this.show_general_ledger();
diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.py b/erpnext/stock/doctype/delivery_note/delivery_note.py
index dc96e7b..37f9097 100644
--- a/erpnext/stock/doctype/delivery_note/delivery_note.py
+++ b/erpnext/stock/doctype/delivery_note/delivery_note.py
@@ -222,6 +222,7 @@
 		self.cancel_packing_slips()
 
 		self.make_gl_entries_on_cancel()
+		self.ignore_linked_doctypes = ('GL Entry', 'Stock Ledger Entry')
 
 	def check_credit_limit(self):
 		from erpnext.selling.doctype.customer.customer import check_credit_limit
diff --git a/erpnext/stock/doctype/delivery_note/regional/india.js b/erpnext/stock/doctype/delivery_note/regional/india.js
index 0c1ca5c..5e1ff98 100644
--- a/erpnext/stock/doctype/delivery_note/regional/india.js
+++ b/erpnext/stock/doctype/delivery_note/regional/india.js
@@ -3,21 +3,28 @@
 erpnext.setup_auto_gst_taxation('Delivery Note');
 
 frappe.ui.form.on('Delivery Note', {
-    refresh: function(frm) {
-        if(frm.doc.docstatus == 1 && !frm.is_dirty() && !frm.doc.ewaybill) {
+	refresh: function(frm) {
+		if(frm.doc.docstatus == 1 && !frm.is_dirty() && !frm.doc.ewaybill) {
 			frm.add_custom_button('E-Way Bill JSON', () => {
-				var w = window.open(
-					frappe.urllib.get_full_url(
-						"/api/method/erpnext.regional.india.utils.generate_ewb_json?"
-						+ "dt=" + encodeURIComponent(frm.doc.doctype)
-						+ "&dn=" + encodeURIComponent(frm.doc.name)
-					)
-				);
-				if (!w) {
-					frappe.msgprint(__("Please enable pop-ups")); return;
-				}
+				frappe.call({
+					method: 'erpnext.regional.india.utils.generate_ewb_json',
+					args: {
+						'dt': frm.doc.doctype,
+						'dn': [frm.doc.name]
+					},
+					callback: function(r) {
+						if (r.message) {
+							const args = {
+								cmd: 'erpnext.regional.india.utils.download_ewb_json',
+								data: r.message,
+								docname: frm.doc.name
+							};
+							open_url_post(frappe.request.url, args);
+						}
+					}
+				});
 			}, __("Create"));
 		}
-    }
+	}
 })
 
diff --git a/erpnext/stock/doctype/delivery_note/test_delivery_note.py b/erpnext/stock/doctype/delivery_note/test_delivery_note.py
index d7a93fb..bf7007a 100644
--- a/erpnext/stock/doctype/delivery_note/test_delivery_note.py
+++ b/erpnext/stock/doctype/delivery_note/test_delivery_note.py
@@ -61,54 +61,55 @@
 
 		self.assertFalse(get_gl_entries("Delivery Note", dn.name))
 
-	def test_delivery_note_gl_entry(self):
-		company = frappe.db.get_value('Warehouse', 'Stores - TCP1', 'company')
+	# def test_delivery_note_gl_entry(self):
+	# 	company = frappe.db.get_value('Warehouse', 'Stores - TCP1', 'company')
 
-		set_valuation_method("_Test Item", "FIFO")
+	# 	set_valuation_method("_Test Item", "FIFO")
 
-		make_stock_entry(target="Stores - TCP1", qty=5, basic_rate=100)
+	# 	make_stock_entry(target="Stores - TCP1", qty=5, basic_rate=100)
 
-		stock_in_hand_account = get_inventory_account('_Test Company with perpetual inventory')
-		prev_bal = get_balance_on(stock_in_hand_account)
+	# 	stock_in_hand_account = get_inventory_account('_Test Company with perpetual inventory')
+	# 	prev_bal = get_balance_on(stock_in_hand_account)
 
-		dn = create_delivery_note(company='_Test Company with perpetual inventory', warehouse='Stores - TCP1', cost_center = 'Main - TCP1', expense_account = "Cost of Goods Sold - TCP1")
+	# 	dn = create_delivery_note(company='_Test Company with perpetual inventory', warehouse='Stores - TCP1', cost_center = 'Main - TCP1', expense_account = "Cost of Goods Sold - TCP1")
 
-		gl_entries = get_gl_entries("Delivery Note", dn.name)
-		self.assertTrue(gl_entries)
+	# 	gl_entries = get_gl_entries("Delivery Note", dn.name)
+	# 	self.assertTrue(gl_entries)
 
-		stock_value_difference = abs(frappe.db.get_value("Stock Ledger Entry",
-			{"voucher_type": "Delivery Note", "voucher_no": dn.name}, "stock_value_difference"))
+	# 	stock_value_difference = abs(frappe.db.get_value("Stock Ledger Entry",
+	# 		{"voucher_type": "Delivery Note", "voucher_no": dn.name}, "stock_value_difference"))
 
-		expected_values = {
-			stock_in_hand_account: [0.0, stock_value_difference],
-			"Cost of Goods Sold - TCP1": [stock_value_difference, 0.0]
-		}
-		for i, gle in enumerate(gl_entries):
-			self.assertEqual([gle.debit, gle.credit], expected_values.get(gle.account))
+	# 	expected_values = {
+	# 		stock_in_hand_account: [0.0, stock_value_difference],
+	# 		"Cost of Goods Sold - TCP1": [stock_value_difference, 0.0]
+	# 	}
+	# 	for i, gle in enumerate(gl_entries):
+	# 		self.assertEqual([gle.debit, gle.credit], expected_values.get(gle.account))
 
-		# check stock in hand balance
-		bal = get_balance_on(stock_in_hand_account)
-		self.assertEqual(bal, prev_bal - stock_value_difference)
+	# 	# check stock in hand balance
+	# 	bal = get_balance_on(stock_in_hand_account)
+	# 	self.assertEqual(bal, prev_bal - stock_value_difference)
 
-		# back dated incoming entry
-		make_stock_entry(posting_date=add_days(nowdate(), -2), target="Stores - TCP1",
-			qty=5, basic_rate=100)
+	# 	# back dated incoming entry
+	# 	make_stock_entry(posting_date=add_days(nowdate(), -2), target="Stores - TCP1",
+	# 		qty=5, basic_rate=100)
 
-		gl_entries = get_gl_entries("Delivery Note", dn.name)
-		self.assertTrue(gl_entries)
+	# 	gl_entries = get_gl_entries("Delivery Note", dn.name)
+	# 	self.assertTrue(gl_entries)
 
-		stock_value_difference = abs(frappe.db.get_value("Stock Ledger Entry",
-			{"voucher_type": "Delivery Note", "voucher_no": dn.name}, "stock_value_difference"))
+	# 	stock_value_difference = abs(frappe.db.get_value("Stock Ledger Entry",
+	# 		{"voucher_type": "Delivery Note", "voucher_no": dn.name}, "stock_value_difference"))
 
-		expected_values = {
-			stock_in_hand_account: [0.0, stock_value_difference],
-			"Cost of Goods Sold - TCP1": [stock_value_difference, 0.0]
-		}
-		for i, gle in enumerate(gl_entries):
-			self.assertEqual([gle.debit, gle.credit], expected_values.get(gle.account))
+	# 	expected_values = {
+	# 		stock_in_hand_account: [0.0, stock_value_difference],
+	# 		"Cost of Goods Sold - TCP1": [stock_value_difference, 0.0]
+	# 	}
+	# 	for i, gle in enumerate(gl_entries):
+	# 		self.assertEqual([gle.debit, gle.credit], expected_values.get(gle.account))
 
-		dn.cancel()
-		self.assertFalse(get_gl_entries("Delivery Note", dn.name))
+	# 	dn.cancel()
+	# 	self.assertTrue(get_gl_entries("Delivery Note", dn.name))
+	# 	set_perpetual_inventory(0, company)
 
 	def test_delivery_note_gl_entry_packing_item(self):
 		company = frappe.db.get_value('Warehouse', 'Stores - TCP1', 'company')
@@ -147,7 +148,6 @@
 		self.assertEqual(flt(bal, 2), flt(prev_bal - stock_value_diff, 2))
 
 		dn.cancel()
-		self.assertFalse(get_gl_entries("Delivery Note", dn.name))
 
 	def test_serialized(self):
 		se = make_serialized_item()
@@ -464,27 +464,19 @@
 		frappe.db.set_value("Stock Settings", None, "allow_negative_stock", 1)
 
 		dn1 = make_delivery_note(so.name)
-		dn1.set_posting_time = 1
-		dn1.posting_time = "10:00"
 		dn1.get("items")[0].qty = 2
 		dn1.submit()
 
+		dn2 = make_delivery_note(so.name)
+		dn2.get("items")[0].qty = 3
+		dn2.submit()
+
+		dn1.load_from_db()
 		self.assertEqual(dn1.get("items")[0].billed_amt, 200)
 		self.assertEqual(dn1.per_billed, 100)
 		self.assertEqual(dn1.status, "Completed")
 
-		dn2 = make_delivery_note(so.name)
-		dn2.set_posting_time = 1
-		dn2.posting_time = "08:00"
-		dn2.get("items")[0].qty = 4
-		dn2.submit()
-
-		dn1.load_from_db()
-		self.assertEqual(dn1.get("items")[0].billed_amt, 100)
-		self.assertEqual(dn1.per_billed, 50)
-		self.assertEqual(dn1.status, "To Bill")
-
-		self.assertEqual(dn2.get("items")[0].billed_amt, 400)
+		self.assertEqual(dn2.get("items")[0].billed_amt, 300)
 		self.assertEqual(dn2.per_billed, 100)
 		self.assertEqual(dn2.status, "Completed")
 
@@ -497,8 +489,6 @@
 		so = make_sales_order()
 
 		dn1 = make_delivery_note(so.name)
-		dn1.set_posting_time = 1
-		dn1.posting_time = "10:00"
 		dn1.get("items")[0].qty = 2
 		dn1.submit()
 
@@ -513,7 +503,6 @@
 		si2.submit()
 
 		dn2 = make_delivery_note(so.name)
-		dn2.posting_time = "08:00"
 		dn2.get("items")[0].qty = 5
 		dn2.submit()
 
diff --git a/erpnext/stock/doctype/delivery_trip/delivery_trip.js b/erpnext/stock/doctype/delivery_trip/delivery_trip.js
index a025f06..a6fbb66 100755
--- a/erpnext/stock/doctype/delivery_trip/delivery_trip.js
+++ b/erpnext/stock/doctype/delivery_trip/delivery_trip.js
@@ -95,8 +95,6 @@
 		};
 	},
 
-	},
-
 	optimize_route: function (frm) {
 		if (!frm.doc.driver_address) {
 			frappe.throw(__("Cannot Optimize Route as Driver Address is Missing."));
diff --git a/erpnext/stock/doctype/item/item.json b/erpnext/stock/doctype/item/item.json
index 7d2e311..c371999 100644
--- a/erpnext/stock/doctype/item/item.json
+++ b/erpnext/stock/doctype/item/item.json
@@ -1060,7 +1060,7 @@
  "image_field": "image",
  "links": [],
  "max_attachments": 1,
- "modified": "2020-04-07 15:56:06.195722",
+ "modified": "2020-04-08 15:56:06.195722",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Item",
@@ -1122,4 +1122,4 @@
  "sort_order": "DESC",
  "title_field": "item_name",
  "track_changes": 1
-}
\ No newline at end of file
+}
diff --git a/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.py b/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.py
index 5ad0e13..bc3d326 100644
--- a/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.py
+++ b/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.py
@@ -137,7 +137,7 @@
 			# update stock & gl entries for cancelled state of PR
 			doc.docstatus = 2
 			doc.update_stock_ledger(allow_negative_stock=True, via_landed_cost_voucher=True)
-			doc.make_gl_entries_on_cancel(repost_future_gle=False)
+			doc.make_gl_entries_on_cancel()
 
 			# update stock & gl entries for submit state of PR
 			doc.docstatus = 1
diff --git a/erpnext/stock/doctype/landed_cost_voucher/test_landed_cost_voucher.py b/erpnext/stock/doctype/landed_cost_voucher/test_landed_cost_voucher.py
index 62d369c..3f2c5da 100644
--- a/erpnext/stock/doctype/landed_cost_voucher/test_landed_cost_voucher.py
+++ b/erpnext/stock/doctype/landed_cost_voucher/test_landed_cost_voucher.py
@@ -15,8 +15,9 @@
 	def test_landed_cost_voucher(self):
 		frappe.db.set_value("Buying Settings", None, "allow_multiple_items", 1)
 
-		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)
 
 		last_sle = frappe.db.get_value("Stock Ledger Entry", {
 				"voucher_type": pr.doctype,
@@ -26,7 +27,7 @@
 			},
 			fieldname=["qty_after_transaction", "stock_value"], as_dict=1)
 
-		submit_landed_cost_voucher("Purchase Receipt", pr.name)
+		submit_landed_cost_voucher("Purchase Receipt", pr.name, pr.company)
 
 		pr_lc_value = frappe.db.get_value("Purchase Receipt Item", {"parent": pr.name}, "landed_cost_voucher_amount")
 		self.assertEqual(pr_lc_value, 25.0)
@@ -67,8 +68,9 @@
 			}
 
 		for gle in gl_entries:
-			self.assertEqual(expected_values[gle.account][0], gle.debit)
-			self.assertEqual(expected_values[gle.account][1], gle.credit)
+			if not gle.get('is_cancelled'):
+				self.assertEqual(expected_values[gle.account][0], gle.debit)
+				self.assertEqual(expected_values[gle.account][1], gle.credit)
 
 
 	def test_landed_cost_voucher_against_purchase_invoice(self):
@@ -87,7 +89,7 @@
 			},
 			fieldname=["qty_after_transaction", "stock_value"], as_dict=1)
 
-		submit_landed_cost_voucher("Purchase Invoice", pi.name)
+		submit_landed_cost_voucher("Purchase Invoice", pi.name, pi.company)
 
 		pi_lc_value = frappe.db.get_value("Purchase Invoice Item", {"parent": pi.name},
 			"landed_cost_voucher_amount")
@@ -118,8 +120,9 @@
 		}
 
 		for gle in gl_entries:
-			self.assertEqual(expected_values[gle.account][0], gle.debit)
-			self.assertEqual(expected_values[gle.account][1], gle.credit)
+			if not gle.get('is_cancelled'):
+				self.assertEqual(expected_values[gle.account][0], gle.debit)
+				self.assertEqual(expected_values[gle.account][1], gle.credit)
 
 
 	def test_landed_cost_voucher_for_serialized_item(self):
@@ -134,7 +137,7 @@
 
 		serial_no_rate = frappe.db.get_value("Serial No", "SN001", "purchase_rate")
 
-		submit_landed_cost_voucher("Purchase Receipt", pr.name)
+		submit_landed_cost_voucher("Purchase Receipt", pr.name, pr.company)
 
 		serial_no = frappe.db.get_value("Serial No", "SN001",
 			["warehouse", "purchase_rate"], as_dict=1)
@@ -157,13 +160,13 @@
 			})
 		pr.submit()
 
-		lcv = submit_landed_cost_voucher("Purchase Receipt", pr.name, 123.22)
+		lcv = submit_landed_cost_voucher("Purchase Receipt", pr.name, pr.company, 123.22)
 
 		self.assertEqual(lcv.items[0].applicable_charges, 41.07)
 		self.assertEqual(lcv.items[2].applicable_charges, 41.08)
 
 	def test_multiple_landed_cost_voucher_against_pr(self):
-		pr = make_purchase_receipt(company="_Test Company with perpetual inventory", warehouse = "Stores - TCP1", 
+		pr = make_purchase_receipt(company="_Test Company with perpetual inventory", warehouse = "Stores - TCP1",
 			supplier_warehouse = "Stores - TCP1", do_not_save=True)
 
 		pr.append("items", {
@@ -176,7 +179,7 @@
 
 		pr.submit()
 
-		lcv1 = make_landed_cost_voucher(receipt_document_type = 'Purchase Receipt', 
+		lcv1 = make_landed_cost_voucher(company = pr.company, receipt_document_type = 'Purchase Receipt',
 			receipt_document=pr.name, charges=100, do_not_save=True)
 
 		lcv1.insert()
@@ -187,7 +190,7 @@
 
 		lcv1.submit()
 
-		lcv2 = make_landed_cost_voucher(receipt_document_type = 'Purchase Receipt', 
+		lcv2 = make_landed_cost_voucher(company = pr.company, receipt_document_type = 'Purchase Receipt',
 			receipt_document=pr.name, charges=100, do_not_save=True)
 
 		lcv2.insert()
@@ -208,7 +211,7 @@
 	ref_doc = frappe.get_doc(args.receipt_document_type, args.receipt_document)
 
 	lcv = frappe.new_doc('Landed Cost Voucher')
-	lcv.company = '_Test Company'
+	lcv.company = args.company or '_Test Company'
 	lcv.distribute_charges_based_on = 'Amount'
 
 	lcv.set('purchase_receipts', [{
@@ -233,11 +236,11 @@
 	return lcv
 
 
-def submit_landed_cost_voucher(receipt_document_type, receipt_document, charges=50):
+def submit_landed_cost_voucher(receipt_document_type, receipt_document, company, charges=50):
 	ref_doc = frappe.get_doc(receipt_document_type, receipt_document)
 
 	lcv = frappe.new_doc("Landed Cost Voucher")
-	lcv.company = "_Test Company"
+	lcv.company = company
 	lcv.distribute_charges_based_on = 'Amount'
 
 	lcv.set("purchase_receipts", [{
diff --git a/erpnext/stock/doctype/material_request/material_request.js b/erpnext/stock/doctype/material_request/material_request.js
index b97da69..db8bffd 100644
--- a/erpnext/stock/doctype/material_request/material_request.js
+++ b/erpnext/stock/doctype/material_request/material_request.js
@@ -20,6 +20,17 @@
 		frm.set_indicator_formatter('item_code',
 			function(doc) { return (doc.qty<=doc.ordered_qty) ? "green" : "orange"; });
 
+		frm.set_query("item_code", "items", function() {
+			return {
+				query: "erpnext.controllers.queries.item_query"
+			};
+		});
+
+		frm.set_query("from_warehouse", "items", function(doc) {
+			return {
+				filters: {'company': doc.company}
+			};
+		})
 	},
 
 	onload: function(frm) {
@@ -53,6 +64,16 @@
 		frm.toggle_reqd('customer', frm.doc.material_request_type=="Customer Provided");
 	},
 
+	set_from_warehouse: function(frm) {
+		if (frm.doc.material_request_type == "Material Transfer"
+			&& frm.doc.set_from_warehouse) {
+			frm.doc.items.forEach(d => {
+				frappe.model.set_value(d.doctype, d.name,
+					"from_warehouse", frm.doc.set_from_warehouse);
+			})
+		}
+	},
+
 	make_custom_buttons: function(frm) {
 		if (frm.doc.docstatus==0) {
 			frm.add_custom_button(__("Bill of Materials"),
@@ -159,6 +180,7 @@
 			args: {
 				args: {
 					item_code: item.item_code,
+					from_warehouse: item.from_warehouse,
 					warehouse: item.warehouse,
 					doctype: frm.doc.doctype,
 					buying_price_list: frappe.defaults.get_default('buying_price_list'),
@@ -176,9 +198,11 @@
 			},
 			callback: function(r) {
 				const d = item;
+				const qty_fields = ['actual_qty', 'projected_qty', 'min_order_qty'];
+
 				if(!r.exc) {
 					$.each(r.message, function(k, v) {
-						if(!d[k]) d[k] = v;
+						if(!d[k] || in_list(qty_fields, k)) d[k] = v;
 					});
 				}
 			}
@@ -299,6 +323,7 @@
 			args: {
 				"material_request": frm.doc.name
 			},
+			freeze: true,
 			callback: function(r) {
 				if(r.message.length) {
 					frm.reload_doc();
@@ -323,6 +348,16 @@
 		frm.events.get_item_data(frm, item);
 	},
 
+	from_warehouse: function(frm, doctype, name) {
+		const item = locals[doctype][name];
+		frm.events.get_item_data(frm, item);
+	},
+
+	warehouse: function(frm, doctype, name) {
+		const item = locals[doctype][name];
+		frm.events.get_item_data(frm, item);
+	},
+
 	rate: function(frm, doctype, name) {
 		const item = locals[doctype][name];
 		frm.events.get_item_data(frm, item);
diff --git a/erpnext/stock/doctype/material_request/material_request.json b/erpnext/stock/doctype/material_request/material_request.json
index 536f5fa..d1f29e3 100644
--- a/erpnext/stock/doctype/material_request/material_request.json
+++ b/erpnext/stock/doctype/material_request/material_request.json
@@ -18,6 +18,8 @@
   "amended_from",
   "warehouse_section",
   "set_warehouse",
+  "column_break5",
+  "set_from_warehouse",
   "items_section",
   "scan_barcode",
   "items",
@@ -287,13 +289,27 @@
    "fieldtype": "Link",
    "label": "Set Warehouse",
    "options": "Warehouse"
+  },
+  {
+   "fieldname": "column_break5",
+   "fieldtype": "Column Break",
+   "oldfieldtype": "Column Break",
+   "print_width": "50%",
+   "width": "50%"
+  },
+  {
+   "depends_on": "eval:doc.material_request_type == 'Material Transfer'",
+   "fieldname": "set_from_warehouse",
+   "fieldtype": "Link",
+   "label": "Set From Warehouse",
+   "options": "Warehouse"
   }
  ],
  "icon": "fa fa-ticket",
  "idx": 70,
  "is_submittable": 1,
  "links": [],
- "modified": "2020-03-02 20:21:09.990867",
+ "modified": "2020-05-01 20:21:09.990867",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Material Request",
diff --git a/erpnext/stock/doctype/material_request/material_request.py b/erpnext/stock/doctype/material_request/material_request.py
index 2d98557..97606f4 100644
--- a/erpnext/stock/doctype/material_request/material_request.py
+++ b/erpnext/stock/doctype/material_request/material_request.py
@@ -8,7 +8,7 @@
 import frappe
 import json
 
-from frappe.utils import cstr, flt, getdate, new_line_sep, nowdate, add_days
+from frappe.utils import cstr, flt, getdate, new_line_sep, nowdate, add_days, get_link_to_form
 from frappe import msgprint, _
 from frappe.model.mapper import get_mapped_doc
 from erpnext.stock.stock_balance import update_bin_qty, get_indented_qty
@@ -456,6 +456,9 @@
 		if source_parent.material_request_type == "Customer Provided":
 			target.allow_zero_valuation_rate = 1
 
+		if source_parent.material_request_type == "Material Transfer":
+			target.s_warehouse = obj.from_warehouse
+
 	def set_missing_values(source, target):
 		target.purpose = source.material_request_type
 		if source.job_card:
@@ -522,15 +525,22 @@
 
 				work_orders.append(wo_order.name)
 			else:
-				errors.append(_("Row {0}: Bill of Materials not found for the Item {1}").format(d.idx, d.item_code))
+				errors.append(_("Row {0}: Bill of Materials not found for the Item {1}")
+					.format(d.idx, get_link_to_form("Item", d.item_code)))
 
 	if work_orders:
-		message = ["""<a href="#Form/Work Order/%s" target="_blank">%s</a>""" % \
-			(p, p) for p in work_orders]
-		msgprint(_("The following Work Orders were created:") + '\n' + new_line_sep(message))
+		work_orders_list = [get_link_to_form("Work Order", d) for d in work_orders]
+
+		if len(work_orders) > 1:
+			msgprint(_("The following {0} were created: {1}")
+				.format(frappe.bold(_("Work Orders")), '<br>' + ', '.join(work_orders_list)))
+		else:
+			msgprint(_("The {0} {1} created sucessfully")
+				.format(frappe.bold(_("Work Order")), work_orders_list[0]))
 
 	if errors:
-		frappe.throw(_("Work Order cannot be created for following reason:") + '\n' + new_line_sep(errors))
+		frappe.throw(_("Work Order cannot be created for following reason: <br> {0}")
+			.format(new_line_sep(errors)))
 
 	return work_orders
 
diff --git a/erpnext/stock/doctype/material_request_item/material_request_item.json b/erpnext/stock/doctype/material_request_item/material_request_item.json
index 2bdc268..df140ff 100644
--- a/erpnext/stock/doctype/material_request_item/material_request_item.json
+++ b/erpnext/stock/doctype/material_request_item/material_request_item.json
@@ -1,4 +1,5 @@
 {
+ "actions": [],
  "autoname": "hash",
  "creation": "2013-02-22 01:28:02",
  "doctype": "DocType",
@@ -21,6 +22,7 @@
   "quantity_and_warehouse",
   "qty",
   "stock_uom",
+  "from_warehouse",
   "warehouse",
   "col_break2",
   "uom",
@@ -419,12 +421,19 @@
   {
    "fieldname": "col_break4",
    "fieldtype": "Column Break"
+  },
+  {
+   "depends_on": "eval:parent.material_request_type == \"Material Transfer\"",
+   "fieldname": "from_warehouse",
+   "fieldtype": "Link",
+   "label": "Source Warehouse (Material Transfer)",
+   "options": "Warehouse"
   }
  ],
  "idx": 1,
  "istable": 1,
  "links": [],
- "modified": "2020-04-16 09:00:00.992835",
+ "modified": "2020-05-01 09:00:00.992835",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Material Request Item",
diff --git a/erpnext/stock/doctype/pick_list/pick_list.py b/erpnext/stock/doctype/pick_list/pick_list.py
index 616de5e..231af1a 100644
--- a/erpnext/stock/doctype/pick_list/pick_list.py
+++ b/erpnext/stock/doctype/pick_list/pick_list.py
@@ -139,7 +139,7 @@
 	item_location_map[item_doc.item_code] = available_locations
 	return locations
 
-def get_available_item_locations(item_code, from_warehouses, required_qty, company):
+def get_available_item_locations(item_code, from_warehouses, required_qty, company, ignore_validation=False):
 	locations = []
 	if frappe.get_cached_value('Item', item_code, 'has_serial_no'):
 		locations = get_available_item_locations_for_serialized_item(item_code, from_warehouses, required_qty, company)
@@ -152,7 +152,7 @@
 
 	remaining_qty = required_qty - total_qty_available
 
-	if remaining_qty > 0:
+	if remaining_qty > 0 and not ignore_validation:
 		frappe.msgprint(_('{0} units of {1} is not available.')
 			.format(remaining_qty, frappe.get_desk_link('Item', item_code)))
 
diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js
index f3020e0..e9568ee 100644
--- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js
+++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js
@@ -92,7 +92,7 @@
 	refresh: function() {
 		var me = this;
 		this._super();
-		if(this.frm.doc.docstatus===1) {
+		if(this.frm.doc.docstatus > 0) {
 			this.show_stock_ledger();
 			//removed for temporary
 			this.show_general_ledger();
diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
index c2b3892..8dfe1d1 100644
--- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
+++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
@@ -196,6 +196,7 @@
 		# because updating ordered qty in bin depends upon updated ordered qty in PO
 		self.update_stock_ledger()
 		self.make_gl_entries_on_cancel()
+		self.ignore_linked_doctypes = ('GL Entry', 'Stock Ledger Entry')
 		self.delete_auto_created_batches()
 
 	def get_current_stock(self):
diff --git a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py
index 40d7cc2..3d42590 100644
--- a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py
+++ b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py
@@ -51,7 +51,7 @@
 		self.assertEqual(current_bin_stock_value, existing_bin_stock_value + 250)
 
 		self.assertFalse(get_gl_entries("Purchase Receipt", pr.name))
-	
+
 	def test_batched_serial_no_purchase(self):
 		item = frappe.db.exists("Item", {'item_name': 'Batched Serialized Item'})
 		if not item:
@@ -68,7 +68,7 @@
 		pr = make_purchase_receipt(item_code=item.name, qty=5, rate=500)
 
 		self.assertTrue(frappe.db.get_value('Batch', {'item': item.name, 'reference_name': pr.name}))
-		
+
 		pr.load_from_db()
 		batch_no = pr.items[0].batch_no
 		pr.cancel()
@@ -106,7 +106,7 @@
 			self.assertEqual(expected_values[gle.account][1], gle.credit)
 
 		pr.cancel()
-		self.assertFalse(get_gl_entries("Purchase Receipt", pr.name))
+		self.assertTrue(get_gl_entries("Purchase Receipt", pr.name))
 
 	def test_subcontracting(self):
 		from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry
@@ -375,7 +375,7 @@
 
 		location = frappe.db.get_value('Asset', assets[0].name, 'location')
 		self.assertEquals(location, "Test Location")
-	
+
 	def test_purchase_return_with_submitted_asset(self):
 		from erpnext.stock.doctype.purchase_receipt.purchase_receipt import make_purchase_return
 
@@ -397,10 +397,10 @@
 
 		pr_return = make_purchase_return(pr.name)
 		self.assertRaises(frappe.exceptions.ValidationError, pr_return.submit)
-		
+
 		asset.load_from_db()
 		asset.cancel()
-		
+
 		pr_return.submit()
 
 	def test_purchase_receipt_for_enable_allow_cost_center_in_entry_of_bs_account(self):
@@ -505,10 +505,13 @@
 		self.assertEquals(pi2.items[1].qty, 1)
 
 	def test_stock_transfer_from_purchase_receipt(self):
-		set_perpetual_inventory(1)
-		pr = make_purchase_receipt(do_not_save=1)
+		pr1 = make_purchase_receipt(warehouse = 'Work In Progress - TCP1', company="_Test Company with perpetual inventory")
+
+		pr = make_purchase_receipt(company="_Test Company with perpetual inventory",
+			warehouse = "Stores - TCP1", do_not_save=1)
+
 		pr.supplier_warehouse = ''
-		pr.items[0].from_warehouse = '_Test Warehouse 2 - _TC'
+		pr.items[0].from_warehouse = 'Work In Progress - TCP1'
 
 		pr.submit()
 
@@ -518,31 +521,33 @@
 		self.assertFalse(gl_entries)
 
 		expected_sle = {
-			'_Test Warehouse 2 - _TC': -5,
-			'_Test Warehouse - _TC': 5
+			'Work In Progress - TCP1': -5,
+			'Stores - TCP1': 5
 		}
 
 		for sle in sl_entries:
 			self.assertEqual(expected_sle[sle.warehouse], sle.actual_qty)
 
-		set_perpetual_inventory(0)
-
 	def test_stock_transfer_from_purchase_receipt_with_valuation(self):
-		set_perpetual_inventory(1)
-		warehouse = frappe.get_doc('Warehouse', '_Test Warehouse 2 - _TC')
-		warehouse.account = '_Test Account Stock In Hand - _TC'
+		warehouse = frappe.get_doc('Warehouse', 'Work In Progress - TCP1')
+		warehouse.account = '_Test Account Stock In Hand - TCP1'
 		warehouse.save()
 
-		pr = make_purchase_receipt(do_not_save=1)
-		pr.items[0].from_warehouse = '_Test Warehouse 2 - _TC'
+		pr1 = make_purchase_receipt(warehouse = 'Work In Progress - TCP1',
+			company="_Test Company with perpetual inventory")
+
+		pr = make_purchase_receipt(company="_Test Company with perpetual inventory",
+			warehouse = "Stores - TCP1", do_not_save=1)
+
+		pr.items[0].from_warehouse = 'Work In Progress - TCP1'
 		pr.supplier_warehouse = ''
 
 
 		pr.append('taxes', {
 			'charge_type': 'On Net Total',
-			'account_head': '_Test Account Shipping Charges - _TC',
+			'account_head': '_Test Account Shipping Charges - TCP1',
 			'category': 'Valuation and Total',
-			'cost_center': 'Main - _TC',
+			'cost_center': 'Main - TCP1',
 			'description': 'Test',
 			'rate': 9
 		})
@@ -553,14 +558,14 @@
 		sl_entries = get_sl_entries('Purchase Receipt', pr.name)
 
 		expected_gle = [
-			['Stock In Hand - _TC', 272.5, 0.0],
-			['_Test Account Stock In Hand - _TC', 0.0, 250.0],
-			['_Test Account Shipping Charges - _TC', 0.0, 22.5]
+			['Stock In Hand - TCP1', 272.5, 0.0],
+			['_Test Account Stock In Hand - TCP1', 0.0, 250.0],
+			['_Test Account Shipping Charges - TCP1', 0.0, 22.5]
 		]
 
 		expected_sle = {
-			'_Test Warehouse 2 - _TC': -5,
-			'_Test Warehouse - _TC': 5
+			'Work In Progress - TCP1': -5,
+			'Stores - TCP1': 5
 		}
 
 		for sle in sl_entries:
@@ -573,8 +578,6 @@
 
 		warehouse.account = ''
 		warehouse.save()
-		set_perpetual_inventory(0)
-
 
 def get_sl_entries(voucher_type, voucher_no):
 	return frappe.db.sql(""" select actual_qty, warehouse, stock_value_difference
@@ -582,7 +585,7 @@
 		order by posting_time desc""", (voucher_type, voucher_no), as_dict=1)
 
 def get_gl_entries(voucher_type, voucher_no):
-	return frappe.db.sql("""select account, debit, credit, cost_center
+	return frappe.db.sql("""select account, debit, credit, cost_center, is_cancelled
 		from `tabGL Entry` where voucher_type=%s and voucher_no=%s
 		order by account desc""", (voucher_type, voucher_no), as_dict=1)
 
diff --git a/erpnext/stock/doctype/purchase_receipt/test_records.json b/erpnext/stock/doctype/purchase_receipt/test_records.json
index e7ea9af..724e3d7 100644
--- a/erpnext/stock/doctype/purchase_receipt/test_records.json
+++ b/erpnext/stock/doctype/purchase_receipt/test_records.json
@@ -83,5 +83,37 @@
    }
   ],
   "supplier": "_Test Supplier"
+ },
+
+ {
+  "buying_price_list": "_Test Price List",
+  "company": "_Test Company",
+  "conversion_rate": 1.0,
+  "currency": "INR",
+  "doctype": "Purchase Receipt",
+  "base_grand_total": 5000.0,
+  "is_subcontracted": "Yes",
+  "base_net_total": 5000.0,
+  "items": [
+   {
+    "base_amount": 5000.0,
+    "conversion_factor": 1.0,
+    "description": "_Test FG Item",
+    "doctype": "Purchase Receipt Item",
+    "item_code": "_Test FG Item",
+    "item_name": "_Test FG Item",
+    "parentfield": "items",
+    "qty": 10.0,
+    "rate": 500.0,
+    "received_qty": 10.0,
+    "rejected_qty": 0.0,
+    "stock_uom": "_Test UOM",
+    "uom": "_Test UOM",
+    "warehouse": "_Test Warehouse - _TC",
+	"cost_center": "Main - _TC"
+   }
+  ],
+  "supplier": "_Test Supplier",
+  "supplier_warehouse": "_Test Warehouse - _TC"
  }
 ]
\ No newline at end of file
diff --git a/erpnext/stock/doctype/quality_inspection_template/quality_inspection_template.json b/erpnext/stock/doctype/quality_inspection_template/quality_inspection_template.json
index eab08e2..9646f2d 100644
--- a/erpnext/stock/doctype/quality_inspection_template/quality_inspection_template.json
+++ b/erpnext/stock/doctype/quality_inspection_template/quality_inspection_template.json
@@ -1,186 +1,96 @@
 {
- "allow_copy": 0, 
- "allow_guest_to_view": 0, 
- "allow_import": 1, 
- "allow_rename": 1, 
- "autoname": "field:quality_inspection_template_name", 
- "beta": 0, 
- "creation": "2018-01-24 16:23:41.691127", 
- "custom": 0, 
- "docstatus": 0, 
- "doctype": "DocType", 
- "document_type": "", 
- "editable_grid": 1, 
- "engine": "InnoDB", 
+ "actions": [],
+ "allow_import": 1,
+ "allow_rename": 1,
+ "autoname": "field:quality_inspection_template_name",
+ "creation": "2018-01-24 16:23:41.691127",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "quality_inspection_template_name",
+  "item_quality_inspection_parameter"
+ ],
  "fields": [
   {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "quality_inspection_template_name", 
-   "fieldtype": "Data", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Quality Inspection Template Name", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 1, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "quality_inspection_template_name",
+   "fieldtype": "Data",
+   "in_list_view": 1,
+   "label": "Quality Inspection Template Name",
+   "reqd": 1,
+   "unique": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "item_quality_inspection_parameter", 
-   "fieldtype": "Table", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Item Quality Inspection Parameter", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Item Quality Inspection Parameter", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 1, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
+   "fieldname": "item_quality_inspection_parameter",
+   "fieldtype": "Table",
+   "label": "Item Quality Inspection Parameter",
+   "options": "Item Quality Inspection Parameter",
+   "reqd": 1
   }
- ], 
- "has_web_view": 0, 
- "hide_heading": 0, 
- "hide_toolbar": 0, 
- "idx": 0, 
- "image_view": 0, 
- "in_create": 0, 
- "is_submittable": 0, 
- "issingle": 0, 
- "istable": 0, 
- "max_attachments": 0, 
- "modified": "2018-02-21 12:05:29.304432", 
- "modified_by": "Administrator", 
- "module": "Stock", 
- "name": "Quality Inspection Template", 
- "name_case": "", 
- "owner": "Administrator", 
+ ],
+ "links": [
+  {
+   "group": "Quality Inspection",
+   "link_doctype": "Quality Inspection",
+   "link_fieldname": "quality_inspection_template"
+  }
+ ],
+ "modified": "2020-04-26 20:13:02.810132",
+ "modified_by": "Administrator",
+ "module": "Stock",
+ "name": "Quality Inspection Template",
+ "owner": "Administrator",
  "permissions": [
   {
-   "amend": 0, 
-   "apply_user_permissions": 0, 
-   "cancel": 0, 
-   "create": 1, 
-   "delete": 1, 
-   "email": 1, 
-   "export": 1, 
-   "if_owner": 0, 
-   "import": 0, 
-   "permlevel": 0, 
-   "print": 1, 
-   "read": 1, 
-   "report": 1, 
-   "role": "System Manager", 
-   "set_user_permissions": 0, 
-   "share": 1, 
-   "submit": 0, 
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "export": 1,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "System Manager",
+   "share": 1,
    "write": 1
-  }, 
+  },
   {
-   "amend": 0, 
-   "apply_user_permissions": 0, 
-   "cancel": 0, 
-   "create": 1, 
-   "delete": 1, 
-   "email": 1, 
-   "export": 1, 
-   "if_owner": 0, 
-   "import": 0, 
-   "permlevel": 0, 
-   "print": 1, 
-   "read": 1, 
-   "report": 1, 
-   "role": "Stock User", 
-   "set_user_permissions": 0, 
-   "share": 1, 
-   "submit": 0, 
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "export": 1,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "Stock User",
+   "share": 1,
    "write": 1
-  }, 
+  },
   {
-   "amend": 0, 
-   "apply_user_permissions": 0, 
-   "cancel": 0, 
-   "create": 1, 
-   "delete": 1, 
-   "email": 1, 
-   "export": 1, 
-   "if_owner": 0, 
-   "import": 0, 
-   "permlevel": 0, 
-   "print": 1, 
-   "read": 1, 
-   "report": 1, 
-   "role": "Quality Manager", 
-   "set_user_permissions": 0, 
-   "share": 1, 
-   "submit": 0, 
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "export": 1,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "Quality Manager",
+   "share": 1,
    "write": 1
-  }, 
+  },
   {
-   "amend": 0, 
-   "apply_user_permissions": 0, 
-   "cancel": 0, 
-   "create": 1, 
-   "delete": 1, 
-   "email": 1, 
-   "export": 1, 
-   "if_owner": 0, 
-   "import": 0, 
-   "permlevel": 0, 
-   "print": 1, 
-   "read": 1, 
-   "report": 1, 
-   "role": "Manufacturing User", 
-   "set_user_permissions": 0, 
-   "share": 1, 
-   "submit": 0, 
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "export": 1,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "Manufacturing User",
+   "share": 1,
    "write": 1
   }
- ], 
- "quick_entry": 0, 
- "read_only": 0, 
- "read_only_onload": 0, 
- "show_name_in_global_search": 0, 
- "sort_field": "modified", 
- "sort_order": "DESC", 
- "track_changes": 1, 
- "track_seen": 0
+ ],
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
 }
\ No newline at end of file
diff --git a/erpnext/stock/doctype/serial_no/serial_no.py b/erpnext/stock/doctype/serial_no/serial_no.py
index b32c709..914eea3 100644
--- a/erpnext/stock/doctype/serial_no/serial_no.py
+++ b/erpnext/stock/doctype/serial_no/serial_no.py
@@ -130,13 +130,17 @@
 		sle_dict = self.get_stock_ledger_entries(serial_no)
 		if sle_dict:
 			if sle_dict.get("incoming", []):
-				entries["purchase_sle"] = sle_dict["incoming"][0]
+				sle_list = [sle for sle in sle_dict["incoming"] if sle.is_cancelled == 0]
+				if sle_list:
+					entries["purchase_sle"] = sle_list[0]
 
 			if len(sle_dict.get("incoming", [])) - len(sle_dict.get("outgoing", [])) > 0:
 				entries["last_sle"] = sle_dict["incoming"][0]
 			else:
 				entries["last_sle"] = sle_dict["outgoing"][0]
-				entries["delivery_sle"] = sle_dict["outgoing"][0]
+				sle_list = [sle for sle in sle_dict["outgoing"] if sle.is_cancelled == 0]
+				if sle_list:
+					entries["delivery_sle"] = sle_list[0]
 
 		return entries
 
@@ -147,11 +151,11 @@
 
 		for sle in frappe.db.sql("""
 			SELECT voucher_type, voucher_no,
-				posting_date, posting_time, incoming_rate, actual_qty, serial_no
+				posting_date, posting_time, incoming_rate, actual_qty, serial_no, is_cancelled
 			FROM
 				`tabStock Ledger Entry`
 			WHERE
-				item_code=%s AND company = %s AND ifnull(is_cancelled, 'No')='No'
+				item_code=%s AND company = %s
 				AND (serial_no = %s
 					OR serial_no like %s
 					OR serial_no like %s
@@ -171,7 +175,7 @@
 
 	def on_trash(self):
 		sl_entries = frappe.db.sql("""select serial_no from `tabStock Ledger Entry`
-			where serial_no like %s and item_code=%s and ifnull(is_cancelled, 'No')='No'""",
+			where serial_no like %s and item_code=%s""",
 			("%%%s%%" % self.name, self.item_code), as_dict=True)
 
 		# Find the exact match
@@ -221,7 +225,7 @@
 		if serial_nos:
 			frappe.throw(_("Item {0} is not setup for Serial Nos. Column must be blank").format(sle.item_code),
 				SerialNoNotRequiredError)
-	elif sle.is_cancelled == "No":
+	else:
 		if serial_nos:
 			if cint(sle.actual_qty) != flt(sle.actual_qty):
 				frappe.throw(_("Serial No {0} quantity {1} cannot be a fraction").format(sle.item_code, sle.actual_qty))
@@ -239,6 +243,10 @@
 						"delivery_document_no", "delivery_document_type", "warehouse",
 						"purchase_document_no", "company"], as_dict=1)
 
+					if sr and cint(sle.actual_qty) < 0 and sr.warehouse != sle.warehouse:
+						frappe.throw(_("Cannot cancel {0} {1} because Serial No {2} does not belong to the warehouse {3}")
+							.format(sle.voucher_type, sle.voucher_no, serial_no, sle.warehouse), SerialNoWarehouseError)
+
 					if sr.item_code!=sle.item_code:
 						if not allow_serial_nos_with_different_item(serial_no, sle):
 							frappe.throw(_("Serial No {0} does not belong to Item {1}").format(serial_no,
@@ -265,7 +273,7 @@
 								frappe.throw(_("Serial No {0} does not belong to Batch {1}").format(serial_no,
 									sle.batch_no), SerialNoBatchError)
 
-							if sle.is_cancelled=="No" and not sr.warehouse:
+							if not sr.warehouse:
 								frappe.throw(_("Serial No {0} does not belong to any Warehouse")
 									.format(serial_no), SerialNoWarehouseError)
 
@@ -311,12 +319,6 @@
 		elif cint(sle.actual_qty) < 0 or not item_det.serial_no_series:
 			frappe.throw(_("Serial Nos Required for Serialized Item {0}").format(sle.item_code),
 				SerialNoRequiredError)
-	elif serial_nos:
-		for serial_no in serial_nos:
-			sr = frappe.db.get_value("Serial No", serial_no, ["name", "warehouse"], as_dict=1)
-			if sr and cint(sle.actual_qty) < 0 and sr.warehouse != sle.warehouse:
-				frappe.throw(_("Cannot cancel {0} {1} because Serial No {2} does not belong to the warehouse {3}")
-					.format(sle.voucher_type, sle.voucher_no, serial_no, sle.warehouse))
 
 def validate_material_transfer_entry(sle_doc):
 	sle_doc.update({
@@ -324,7 +326,7 @@
 		"skip_serial_no_validaiton": False
 	})
 
-	if (sle_doc.voucher_type == "Stock Entry" and sle_doc.is_cancelled == "No" and
+	if (sle_doc.voucher_type == "Stock Entry" and
 		frappe.get_cached_value("Stock Entry", sle_doc.voucher_no, "purpose") == "Material Transfer"):
 		if sle_doc.actual_qty < 0:
 			sle_doc.skip_update_serial_no = True
@@ -367,7 +369,7 @@
 		stock_entry = frappe.get_cached_doc("Stock Entry", sle.voucher_no)
 		if stock_entry.purpose in ("Repack", "Manufacture"):
 			for d in stock_entry.get("items"):
-				if d.serial_no and (d.s_warehouse if sle.is_cancelled=="No" else d.t_warehouse):
+				if d.serial_no and (d.s_warehouse or d.t_warehouse):
 					serial_nos = get_serial_nos(d.serial_no)
 					if sle_serial_no in serial_nos:
 						allow_serial_nos = True
@@ -376,7 +378,7 @@
 
 def update_serial_nos(sle, item_det):
 	if sle.skip_update_serial_no: return
-	if sle.is_cancelled == "No" and not sle.serial_no and cint(sle.actual_qty) > 0 \
+	if not sle.serial_no and cint(sle.actual_qty) > 0 \
 			and item_det.has_serial_no == 1 and item_det.serial_no_series:
 		serial_nos = get_auto_serial_nos(item_det.serial_no_series, sle.actual_qty)
 		frappe.db.set(sle, "serial_no", serial_nos)
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.js b/erpnext/stock/doctype/stock_entry/stock_entry.js
index 8e3d323..53b986c 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.js
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.js
@@ -215,9 +215,7 @@
 					source_doctype: "Material Request",
 					target: frm,
 					date_field: "schedule_date",
-					setters: {
-						company: frm.doc.company,
-					},
+					setters: {},
 					get_query_filters: {
 						docstatus: 1,
 						material_request_type: ["in", ["Material Transfer", "Material Issue"]],
@@ -312,10 +310,9 @@
 			callback: function(r) {
 				if (!r.exe && r.message){
 					frappe.model.set_value(cdt, cdn, "serial_no", r.message);
-
-					if (callback) {
-						callback();
-					}
+				}
+				if (callback) {
+					callback();
 				}
 			}
 		});
@@ -511,9 +508,10 @@
 			item.amount = flt(item.basic_amount + flt(item.additional_cost),
 				precision("amount", item));
 
-			item.valuation_rate = flt(flt(item.basic_rate)
-				+ (flt(item.additional_cost) / flt(item.transfer_qty)),
-				precision("valuation_rate", item));
+			if (flt(item.transfer_qty)) {
+				item.valuation_rate = flt(flt(item.basic_rate) + (flt(item.additional_cost) / flt(item.transfer_qty)),
+					precision("valuation_rate", item));
+			}
 		}
 
 		refresh_field('items');
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.json b/erpnext/stock/doctype/stock_entry/stock_entry.json
index bdd0bd0..704ae41 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.json
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.json
@@ -1,4 +1,5 @@
 {
+ "actions": [],
  "allow_import": 1,
  "autoname": "naming_series:",
  "creation": "2013-04-09 11:43:55",
@@ -12,7 +13,6 @@
   "stock_entry_type",
   "outgoing_stock_entry",
   "purpose",
-  "company",
   "work_order",
   "purchase_order",
   "delivery_note_no",
@@ -20,6 +20,7 @@
   "pick_list",
   "purchase_receipt_no",
   "col2",
+  "company",
   "posting_date",
   "posting_time",
   "set_posting_time",
@@ -65,6 +66,7 @@
   "dimension_col_break",
   "printing_settings",
   "select_print_heading",
+  "print_settings_col_break",
   "letter_head",
   "more_info",
   "is_opening",
@@ -291,6 +293,7 @@
    "fieldtype": "Section Break"
   },
   {
+   "description": "Sets 'Source Warehouse' in each row of the items table.",
    "fieldname": "from_warehouse",
    "fieldtype": "Link",
    "in_list_view": 1,
@@ -320,6 +323,7 @@
    "fieldtype": "Column Break"
   },
   {
+   "description": "Sets 'Target Warehouse' in each row of the items table.",
    "fieldname": "to_warehouse",
    "fieldtype": "Link",
    "in_list_view": 1,
@@ -622,12 +626,17 @@
    "label": "Pick List",
    "options": "Pick List",
    "read_only": 1
+  },
+  {
+   "fieldname": "print_settings_col_break",
+   "fieldtype": "Column Break"
   }
  ],
  "icon": "fa fa-file-text",
  "idx": 1,
  "is_submittable": 1,
- "modified": "2019-09-27 14:38:20.801420",
+ "links": [],
+ "modified": "2020-04-23 12:56:52.881752",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Stock Entry",
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py
index 95f9d46..ddf4ec0 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.py
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.py
@@ -107,6 +107,9 @@
 
 		self.update_work_order()
 		self.update_stock_ledger()
+
+		self.ignore_linked_doctypes = ('GL Entry', 'Stock Ledger Entry')
+
 		self.make_gl_entries_on_cancel()
 		self.update_cost_in_project()
 		self.update_transferred_qty()
@@ -651,7 +654,7 @@
 		if self.docstatus == 2:
 			sl_entries.reverse()
 
-		self.make_sl_entries(sl_entries, self.amended_from and 'Yes' or 'No')
+		self.make_sl_entries(sl_entries)
 
 	def get_gl_entries(self, warehouse_account):
 		gl_entries = super(StockEntry, self).get_gl_entries(warehouse_account)
@@ -674,7 +677,7 @@
 					multiply_based_on = d.basic_amount if total_basic_amount else d.qty
 
 					item_account_wise_additional_cost[(d.item_code, d.name)][t.expense_account] += \
-						(t.amount * multiply_based_on) / divide_based_on
+						flt(t.amount * multiply_based_on) / divide_based_on
 
 		if item_account_wise_additional_cost:
 			for d in self.get("items"):
@@ -1050,9 +1053,9 @@
 				fields=["required_qty", "consumed_qty"]
 				)
 
-			req_qty = flt(req_items[0].required_qty)
+			req_qty = flt(req_items[0].required_qty) if req_items else flt(4)
 			req_qty_each = flt(req_qty / manufacturing_qty)
-			consumed_qty = flt(req_items[0].consumed_qty)
+			consumed_qty = flt(req_items[0].consumed_qty) if req_items else 0
 
 			if trans_qty and manufacturing_qty > (produced_qty + flt(self.fg_completed_qty)):
 				if qty >= req_qty:
diff --git a/erpnext/stock/doctype/stock_entry/test_records.json b/erpnext/stock/doctype/stock_entry/test_records.json
index cfbdce4..dc21287 100644
--- a/erpnext/stock/doctype/stock_entry/test_records.json
+++ b/erpnext/stock/doctype/stock_entry/test_records.json
@@ -24,7 +24,6 @@
 	{
 		"company": "_Test Company",
 		"doctype": "Stock Entry",
-		"posting_date": "2013-01-25",
 		"purpose": "Material Issue",
 		"stock_entry_type": "Material Issue",
 		"items": [
@@ -47,7 +46,6 @@
 	{
 		"company": "_Test Company",
 		"doctype": "Stock Entry",
-		"posting_date": "2013-01-25",
 		"purpose": "Material Transfer",
 		"stock_entry_type": "Material Transfer",
 		"items": [
diff --git a/erpnext/stock/doctype/stock_entry/test_stock_entry.py b/erpnext/stock/doctype/stock_entry/test_stock_entry.py
index 2afabe1..0fbc631 100644
--- a/erpnext/stock/doctype/stock_entry/test_stock_entry.py
+++ b/erpnext/stock/doctype/stock_entry/test_stock_entry.py
@@ -149,10 +149,10 @@
 
 		mr.cancel()
 
-		self.assertFalse(frappe.db.sql("""select * from `tabStock Ledger Entry`
+		self.assertTrue(frappe.db.sql("""select * from `tabStock Ledger Entry`
 			where voucher_type='Stock Entry' and voucher_no=%s""", mr.name))
 
-		self.assertFalse(frappe.db.sql("""select * from `tabGL Entry`
+		self.assertTrue(frappe.db.sql("""select * from `tabGL Entry`
 			where voucher_type='Stock Entry' and voucher_no=%s""", mr.name))
 
 	def test_material_issue_gl_entry(self):
@@ -178,12 +178,6 @@
 		)
 		mi.cancel()
 
-		self.assertFalse(frappe.db.sql("""select name from `tabStock Ledger Entry`
-			where voucher_type='Stock Entry' and voucher_no=%s""", mi.name))
-
-		self.assertFalse(frappe.db.sql("""select name from `tabGL Entry`
-			where voucher_type='Stock Entry' and voucher_no=%s""", mi.name))
-
 	def test_material_transfer_gl_entry(self):
 		company = frappe.db.get_value('Warehouse', 'Stores - TCP1', 'company')
 
@@ -216,11 +210,6 @@
 			)
 
 		mtn.cancel()
-		self.assertFalse(frappe.db.sql("""select * from `tabStock Ledger Entry`
-			where voucher_type='Stock Entry' and voucher_no=%s""", mtn.name))
-
-		self.assertFalse(frappe.db.sql("""select * from `tabGL Entry`
-			where voucher_type='Stock Entry' and voucher_no=%s""", mtn.name))
 
 	def test_repack_no_change_in_valuation(self):
 		company = frappe.db.get_value('Warehouse', '_Test Warehouse - _TC', 'company')
@@ -544,10 +533,10 @@
 		frappe.db.set_value("Stock Settings", None, "stock_frozen_upto", '')
 
 		# test freeze_stocks_upto_days
-		frappe.db.set_value("Stock Settings", None, "stock_frozen_upto_days", 7)
+		frappe.db.set_value("Stock Settings", None, "stock_frozen_upto_days", -1)
 		se = frappe.copy_doc(test_records[0])
 		se.set_posting_time = 1
-		se.posting_date = add_days(nowdate(), -15)
+		se.posting_date = nowdate()
 		se.set_stock_entry_type()
 		se.insert()
 		self.assertRaises(StockFreezeError, se.submit)
diff --git a/erpnext/stock/doctype/stock_entry_detail/stock_entry_detail.json b/erpnext/stock/doctype/stock_entry_detail/stock_entry_detail.json
index a848c80..c16a41c 100644
--- a/erpnext/stock/doctype/stock_entry_detail/stock_entry_detail.json
+++ b/erpnext/stock/doctype/stock_entry_detail/stock_entry_detail.json
@@ -14,12 +14,12 @@
   "t_warehouse",
   "sec_break1",
   "item_code",
-  "item_group",
   "col_break2",
   "item_name",
   "section_break_8",
   "description",
   "column_break_10",
+  "item_group",
   "image",
   "image_view",
   "quantity_and_rate",
@@ -178,6 +178,7 @@
    "bold": 1,
    "fieldname": "basic_rate",
    "fieldtype": "Currency",
+   "in_list_view": 1,
    "label": "Basic Rate (as per Stock UOM)",
    "oldfieldname": "incoming_rate",
    "oldfieldtype": "Currency",
@@ -420,6 +421,7 @@
    "options": "Item"
   },
   {
+   "collapsible": 1,
    "fieldname": "reference_section",
    "fieldtype": "Section Break",
    "label": "Reference"
@@ -466,7 +468,6 @@
    "fetch_from": "item_code.item_group",
    "fieldname": "item_group",
    "fieldtype": "Data",
-   "in_list_view": 1,
    "label": "Item Group"
   },
   {
@@ -495,7 +496,7 @@
  "idx": 1,
  "istable": 1,
  "links": [],
- "modified": "2020-03-19 12:34:09.836295",
+ "modified": "2020-04-23 19:19:28.539769",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Stock Entry Detail",
diff --git a/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.json b/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.json
index c03eb79..fda17e0 100644
--- a/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.json
+++ b/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.json
@@ -1,4 +1,5 @@
 {
+ "actions": [],
  "allow_copy": 1,
  "autoname": "MAT-SLE-.YYYY.-.#####",
  "creation": "2013-01-29 19:25:42",
@@ -255,11 +256,10 @@
    "width": "150px"
   },
   {
+   "default": "0",
    "fieldname": "is_cancelled",
-   "fieldtype": "Select",
-   "hidden": 1,
+   "fieldtype": "Check",
    "label": "Is Cancelled",
-   "options": "\nNo\nYes",
    "report_hide": 1
   },
   {
@@ -275,7 +275,8 @@
  "icon": "fa fa-list",
  "idx": 1,
  "in_create": 1,
- "modified": "2020-02-25 22:53:33.504681",
+ "links": [],
+ "modified": "2020-04-23 05:57:03.985520",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Stock Ledger Entry",
diff --git a/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py b/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py
index dab5a7b..101c6e0 100644
--- a/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py
+++ b/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py
@@ -46,7 +46,7 @@
 	def calculate_batch_qty(self):
 		if self.batch_no:
 			batch_qty = frappe.db.get_value("Stock Ledger Entry",
-				{"docstatus": 1, "batch_no": self.batch_no, "is_cancelled": "No"},
+				{"docstatus": 1, "batch_no": self.batch_no},
 				"sum(actual_qty)") or 0
 			frappe.db.set_value("Batch", self.batch_no, "batch_qty", batch_qty)
 
@@ -93,7 +93,7 @@
 				elif not frappe.db.get_value("Batch",{"item": self.item_code, "name": self.batch_no}):
 					frappe.throw(_("{0} is not a valid Batch Number for Item {1}").format(self.batch_no, batch_item))
 
-			elif item_det.has_batch_no ==0 and self.batch_no and self.is_cancelled == "No":
+			elif item_det.has_batch_no ==0 and self.batch_no:
 				frappe.throw(_("The Item {0} cannot have Batch").format(self.item_code))
 
 		if item_det.has_variants:
diff --git a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.js b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.js
index 1791978..dd284e4 100644
--- a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.js
+++ b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.js
@@ -227,7 +227,7 @@
 	},
 
 	refresh: function() {
-		if(this.frm.doc.docstatus==1) {
+		if(this.frm.doc.docstatus > 0) {
 			this.show_stock_ledger();
 			if (erpnext.is_perpetual_inventory_enabled(this.frm.doc.company)) {
 				this.show_general_ledger();
diff --git a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py
index 0a49c26..5e469c2 100644
--- a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py
+++ b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py
@@ -6,7 +6,6 @@
 import frappe.defaults
 from frappe import msgprint, _
 from frappe.utils import cstr, flt, cint
-from erpnext.stock.stock_ledger import update_entries_after
 from erpnext.controllers.stock_controller import StockController
 from erpnext.accounts.utils import get_company_default
 from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos
@@ -43,7 +42,8 @@
 		update_serial_nos_after_submit(self, "items")
 
 	def on_cancel(self):
-		self.delete_and_repost_sle()
+		self.ignore_linked_doctypes = ('GL Entry', 'Stock Ledger Entry')
+		self.make_sle_on_cancel()
 		self.make_gl_entries_on_cancel()
 
 	def remove_items_with_no_change(self):
@@ -193,6 +193,7 @@
 				if row.serial_no or row.batch_no:
 					frappe.throw(_("Row #{0}: Item {1} is not a Serialized/Batched Item. It cannot have a Serial No/Batch No against it.") \
 						.format(row.idx, frappe.bold(row.item_code)))
+
 				previous_sle = get_previous_sle({
 					"item_code": row.item_code,
 					"warehouse": row.warehouse,
@@ -319,7 +320,7 @@
 			"voucher_detail_no": row.name,
 			"company": self.company,
 			"stock_uom": frappe.db.get_value("Item", row.item_code, "stock_uom"),
-			"is_cancelled": "No" if self.docstatus != 2 else "Yes",
+			"is_cancelled": 1 if self.docstatus == 2 else 0,
 			"serial_no": '\n'.join(serial_nos) if serial_nos else '',
 			"batch_no": row.batch_no,
 			"valuation_rate": flt(row.valuation_rate, row.precision("valuation_rate"))
@@ -328,27 +329,35 @@
 		if not row.batch_no:
 			data.qty_after_transaction = flt(row.qty, row.precision("qty"))
 
+		if self.docstatus == 2 and not row.batch_no:
+			if row.current_qty:
+				data.actual_qty = -1 * row.current_qty
+				data.qty_after_transaction = flt(row.current_qty)
+				data.valuation_rate = flt(row.current_valuation_rate)
+				data.stock_value = data.qty_after_transaction * data.valuation_rate
+				data.stock_value_difference = -1 * flt(row.amount_difference)
+			else:
+				data.actual_qty = row.qty
+				data.qty_after_transaction = 0.0
+				data.valuation_rate = flt(row.valuation_rate)
+				data.stock_value_difference = -1 * flt(row.amount_difference)
+
 		return data
 
-	def delete_and_repost_sle(self):
-		"""	Delete Stock Ledger Entries related to this voucher
-			and repost future Stock Ledger Entries"""
-
-		existing_entries = frappe.db.sql("""select distinct item_code, warehouse
-			from `tabStock Ledger Entry` where voucher_type=%s and voucher_no=%s""",
-			(self.doctype, self.name), as_dict=1)
-
-		# delete entries
-		frappe.db.sql("""delete from `tabStock Ledger Entry`
-			where voucher_type=%s and voucher_no=%s""", (self.doctype, self.name))
-
+	def make_sle_on_cancel(self):
 		sl_entries = []
 
 		has_serial_no = False
 		for row in self.items:
 			if row.serial_no or row.batch_no or row.current_serial_no:
 				has_serial_no = True
-				self.get_sle_for_serialized_items(row, sl_entries)
+				serial_nos = ''
+				if row.current_serial_no:
+					serial_nos = get_serial_nos(row.current_serial_no)
+
+				sl_entries.append(self.get_sle_for_items(row, serial_nos))
+			else:
+				sl_entries.append(self.get_sle_for_items(row))
 
 		if sl_entries:
 			if has_serial_no:
@@ -358,14 +367,6 @@
 			allow_negative_stock = frappe.db.get_value("Stock Settings", None, "allow_negative_stock")
 			self.make_sl_entries(sl_entries, allow_negative_stock=allow_negative_stock)
 
-		# repost future entries for selected item_code, warehouse
-		for entries in existing_entries:
-			update_entries_after({
-				"item_code": entries.item_code,
-				"warehouse": entries.warehouse,
-				"posting_date": self.posting_date,
-				"posting_time": self.posting_time
-			})
 
 	def merge_similar_item_serial_nos(self, sl_entries):
 		# If user has put the same item in multiple row with different serial no
@@ -434,12 +435,6 @@
 		else:
 			self._submit()
 
-	def cancel(self):
-		if len(self.items) > 100:
-			self.queue_action('cancel')
-		else:
-			self._cancel()
-
 @frappe.whitelist()
 def get_items(warehouse, posting_date, posting_time, company):
 	lft, rgt = frappe.db.get_value("Warehouse", warehouse, ["lft", "rgt"])
diff --git a/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py b/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py
index 51d027f..1571416 100644
--- a/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py
+++ b/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py
@@ -34,11 +34,11 @@
 		# [[qty, valuation_rate, posting_date,
 		#		posting_time, expected_stock_value, bin_qty, bin_valuation]]
 		input_data = [
-			[50, 1000, "2012-12-26", "12:00"],
-			[25, 900, "2012-12-26", "12:00"],
-			["", 1000, "2012-12-20", "12:05"],
-			[20, "", "2012-12-26", "12:05"],
-			[0, "", "2012-12-31", "12:10"]
+			[50, 1000],
+			[25, 900],
+			["", 1000],
+			[20, ""],
+			[0, ""]
 		]
 
 		for d in input_data:
@@ -47,13 +47,13 @@
 			last_sle = get_previous_sle({
 				"item_code": "_Test Item",
 				"warehouse": "Stores - TCP1",
-				"posting_date": d[2],
-				"posting_time": d[3]
+				"posting_date": nowdate(),
+				"posting_time": nowtime()
 			})
 
 			# submit stock reconciliation
 			stock_reco = create_stock_reconciliation(qty=d[0], rate=d[1],
-				posting_date=d[2], posting_time=d[3], warehouse="Stores - TCP1",
+				posting_date=nowdate(), posting_time=nowtime(), warehouse="Stores - TCP1",
 				company=company, expense_account = "Stock Adjustment - TCP1")
 
 			# check stock value
@@ -68,8 +68,8 @@
 				and valuation_rate == last_sle.get("valuation_rate"):
 					self.assertFalse(sle)
 			else:
-				self.assertEqual(sle[0].qty_after_transaction, qty_after_transaction)
-				self.assertEqual(sle[0].stock_value, qty_after_transaction * valuation_rate)
+				self.assertEqual(flt(sle[0].qty_after_transaction, 1), flt(qty_after_transaction, 1))
+				self.assertEqual(flt(sle[0].stock_value, 1), flt(qty_after_transaction * valuation_rate, 1))
 
 				# no gl entries
 				self.assertTrue(frappe.db.get_value("Stock Ledger Entry",
@@ -77,16 +77,10 @@
 
 				acc_bal, stock_bal, wh_list = get_stock_and_account_balance("Stock In Hand - TCP1",
 					stock_reco.posting_date, stock_reco.company)
-				self.assertEqual(acc_bal, stock_bal)
+				self.assertEqual(flt(acc_bal, 1), flt(stock_bal, 1))
 
 				stock_reco.cancel()
 
-				self.assertFalse(frappe.db.get_value("Stock Ledger Entry",
-					{"voucher_type": "Stock Reconciliation", "voucher_no": stock_reco.name}))
-
-				self.assertFalse(frappe.db.get_value("GL Entry",
-					{"voucher_type": "Stock Reconciliation", "voucher_no": stock_reco.name}))
-
 	def test_get_items(self):
 		create_warehouse("_Test Warehouse Group 1", {"is_group": 1})
 		create_warehouse("_Test Warehouse Ledger 1",
@@ -113,7 +107,6 @@
 		sr = create_stock_reconciliation(item_code=serial_item_code,
 			warehouse = serial_warehouse, qty=5, rate=200)
 
-		# print(sr.name)
 		serial_nos = get_serial_nos(sr.items[0].serial_no)
 		self.assertEqual(len(serial_nos), 5)
 
@@ -133,7 +126,6 @@
 		sr = create_stock_reconciliation(item_code=serial_item_code,
 			warehouse = serial_warehouse, qty=5, rate=300, serial_no = '\n'.join(serial_nos))
 
-		# print(sr.name)
 		serial_nos1 = get_serial_nos(sr.items[0].serial_no)
 		self.assertEqual(len(serial_nos1), 5)
 
@@ -155,10 +147,6 @@
 			stock_doc = frappe.get_doc("Stock Reconciliation", d)
 			stock_doc.cancel()
 
-		for d in serial_nos + serial_nos1:
-			if frappe.db.exists("Serial No", d):
-				frappe.delete_doc("Serial No", d)
-
 	def test_stock_reco_for_batch_item(self):
 		set_perpetual_inventory()
 
@@ -208,13 +196,13 @@
 def insert_existing_sle(warehouse):
 	from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry
 
-	make_stock_entry(posting_date="2012-12-15", posting_time="02:00", item_code="_Test Item",
+	make_stock_entry(posting_date=nowdate(), posting_time=nowtime(), item_code="_Test Item",
 		target=warehouse, qty=10, basic_rate=700)
 
-	make_stock_entry(posting_date="2012-12-25", posting_time="03:00", item_code="_Test Item",
+	make_stock_entry(posting_date=nowdate(), posting_time=nowtime(), item_code="_Test Item",
 		source=warehouse, qty=15)
 
-	make_stock_entry(posting_date="2013-01-05", posting_time="07:00", item_code="_Test Item",
+	make_stock_entry(posting_date=nowdate(), posting_time=nowtime(), item_code="_Test Item",
 		target=warehouse, qty=15, basic_rate=1200)
 
 def create_batch_or_serial_no_items():
diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py
index 61429cc..d50712a 100644
--- a/erpnext/stock/get_item_details.py
+++ b/erpnext/stock/get_item_details.py
@@ -77,7 +77,11 @@
 	if args.customer and cint(args.is_pos):
 		out.update(get_pos_profile_item_details(args.company, args))
 
-	if out.get("warehouse"):
+	if (args.get("doctype") == "Material Request" and
+		args.get("material_request_type") == "Material Transfer"):
+		out.update(get_bin_details(args.item_code, args.get("from_warehouse")))
+
+	elif out.get("warehouse"):
 		out.update(get_bin_details(args.item_code, out.warehouse))
 
 	# update args with out, if key or value not exists
@@ -342,8 +346,14 @@
 			out["manufacturer_part_no"] = None
 			out["manufacturer"] = None
 	else:
-		out["manufacturer"], out["manufacturer_part_no"] = frappe.get_value("Item", item.name,
-			["default_item_manufacturer", "default_manufacturer_part_no"] )
+		data = frappe.get_value("Item", item.name,
+			["default_item_manufacturer", "default_manufacturer_part_no"] , as_dict=1)
+
+		if data:
+			out.update({
+				"manufacturer": data.default_item_manufacturer,
+				"manufacturer_part_no": data.default_manufacturer_part_no
+			})
 
 	child_doctype = args.doctype + ' Item'
 	meta = frappe.get_meta(child_doctype)
diff --git a/erpnext/stock/report/stock_balance/stock_balance.js b/erpnext/stock/report/stock_balance/stock_balance.js
index 537fa7c..7d22823 100644
--- a/erpnext/stock/report/stock_balance/stock_balance.js
+++ b/erpnext/stock/report/stock_balance/stock_balance.js
@@ -4,6 +4,14 @@
 frappe.query_reports["Stock Balance"] = {
 	"filters": [
 		{
+			"fieldname": "company",
+			"label": __("Company"),
+			"fieldtype": "Link",
+			"width": "80",
+			"options": "Company",
+			"default": frappe.defaults.get_default("company")
+		},
+		{
 			"fieldname":"from_date",
 			"label": __("From Date"),
 			"fieldtype": "Date",
@@ -27,12 +35,6 @@
 			"options": "Item Group"
 		},
 		{
-			"fieldname":"brand",
-			"label": __("Brand"),
-			"fieldtype": "Link",
-			"options": "Brand"
-		},
-		{
 			"fieldname": "item_code",
 			"label": __("Item"),
 			"fieldtype": "Link",
@@ -84,5 +86,18 @@
 			"label": __('Show Stock Ageing Data'),
 			"fieldtype": 'Check'
 		},
-	]
+	],
+
+	"formatter": function (value, row, column, data, default_formatter) {
+		value = default_formatter(value, row, column, data);
+
+		if (column.fieldname == "out_qty" && data && data.out_qty > 0) {
+			value = "<span style='color:red'>" + value + "</span>";
+		}
+		else if (column.fieldname == "in_qty" && data && data.in_qty > 0) {
+			value = "<span style='color:green'>" + value + "</span>";
+		}
+
+		return value;
+	}
 };
diff --git a/erpnext/stock/report/stock_balance/stock_balance.json b/erpnext/stock/report/stock_balance/stock_balance.json
index 2f20b20..8c45f0c 100644
--- a/erpnext/stock/report/stock_balance/stock_balance.json
+++ b/erpnext/stock/report/stock_balance/stock_balance.json
@@ -1,24 +1,26 @@
 {
- "add_total_row": 1, 
- "creation": "2014-10-10 17:58:11.577901", 
- "disabled": 0, 
- "docstatus": 0, 
- "doctype": "Report", 
- "idx": 2, 
- "is_standard": "Yes", 
- "modified": "2018-08-14 15:24:41.395557", 
- "modified_by": "Administrator", 
- "module": "Stock", 
- "name": "Stock Balance", 
- "owner": "Administrator", 
- "prepared_report": 1, 
- "ref_doctype": "Stock Ledger Entry", 
- "report_name": "Stock Balance", 
- "report_type": "Script Report", 
+ "add_total_row": 1,
+ "creation": "2014-10-10 17:58:11.577901",
+ "disable_prepared_report": 0,
+ "disabled": 0,
+ "docstatus": 0,
+ "doctype": "Report",
+ "idx": 2,
+ "is_standard": "Yes",
+ "modified": "2020-04-30 13:46:14.680354",
+ "modified_by": "Administrator",
+ "module": "Stock",
+ "name": "Stock Balance",
+ "owner": "Administrator",
+ "prepared_report": 1,
+ "query": "",
+ "ref_doctype": "Stock Ledger Entry",
+ "report_name": "Stock Balance",
+ "report_type": "Script Report",
  "roles": [
   {
    "role": "Stock User"
-  }, 
+  },
   {
    "role": "Accounts Manager"
   }
diff --git a/erpnext/stock/report/stock_balance/stock_balance.py b/erpnext/stock/report/stock_balance/stock_balance.py
index ff03381..74a4f6e 100644
--- a/erpnext/stock/report/stock_balance/stock_balance.py
+++ b/erpnext/stock/report/stock_balance/stock_balance.py
@@ -94,8 +94,6 @@
 		{"label": _("Item"), "fieldname": "item_code", "fieldtype": "Link", "options": "Item", "width": 100},
 		{"label": _("Item Name"), "fieldname": "item_name", "width": 150},
 		{"label": _("Item Group"), "fieldname": "item_group", "fieldtype": "Link", "options": "Item Group", "width": 100},
-		{"label": _("Brand"), "fieldname": "brand", "fieldtype": "Link", "options": "Brand", "width": 90},
-		{"label": _("Description"), "fieldname": "description", "width": 140},
 		{"label": _("Warehouse"), "fieldname": "warehouse", "fieldtype": "Link", "options": "Warehouse", "width": 100},
 		{"label": _("Stock UOM"), "fieldname": "stock_uom", "fieldtype": "Link", "options": "UOM", "width": 90},
 		{"label": _("Balance Qty"), "fieldname": "bal_qty", "fieldtype": "Float", "width": 100, "convertible": "qty"},
@@ -132,6 +130,9 @@
 	else:
 		frappe.throw(_("'To Date' is required"))
 
+	if filters.get("company"):
+		conditions += " and sle.company = %s" % frappe.db.escape(filters.get("company"))
+
 	if filters.get("warehouse"):
 		warehouse_details = frappe.db.get_value("Warehouse",
 			filters.get("warehouse"), ["lft", "rgt"], as_dict=1)
@@ -170,6 +171,8 @@
 	from_date = getdate(filters.get("from_date"))
 	to_date = getdate(filters.get("to_date"))
 
+	float_precision = cint(frappe.db.get_default("float_precision")) or 3
+
 	for d in sle:
 		key = (d.company, d.item_code, d.warehouse)
 		if key not in iwb_map:
@@ -184,7 +187,7 @@
 		qty_dict = iwb_map[(d.company, d.item_code, d.warehouse)]
 
 		if d.voucher_type == "Stock Reconciliation":
-			qty_diff = flt(d.qty_after_transaction) - qty_dict.bal_qty
+			qty_diff = flt(d.qty_after_transaction) - flt(qty_dict.bal_qty)
 		else:
 			qty_diff = flt(d.actual_qty)
 
@@ -195,7 +198,7 @@
 			qty_dict.opening_val += value_diff
 
 		elif d.posting_date >= from_date and d.posting_date <= to_date:
-			if qty_diff > 0:
+			if flt(qty_diff, float_precision) >= 0:
 				qty_dict.in_qty += qty_diff
 				qty_dict.in_val += value_diff
 			else:
@@ -206,16 +209,15 @@
 		qty_dict.bal_qty += qty_diff
 		qty_dict.bal_val += value_diff
 
-	iwb_map = filter_items_with_no_transactions(iwb_map)
+	iwb_map = filter_items_with_no_transactions(iwb_map, float_precision)
 
 	return iwb_map
 
-def filter_items_with_no_transactions(iwb_map):
+def filter_items_with_no_transactions(iwb_map, float_precision):
 	for (company, item, warehouse) in sorted(iwb_map):
 		qty_dict = iwb_map[(company, item, warehouse)]
 
 		no_transactions = True
-		float_precision = cint(frappe.db.get_default("float_precision")) or 3
 		for key, val in iteritems(qty_dict):
 			val = flt(val, float_precision)
 			qty_dict[key] = val
@@ -232,8 +234,6 @@
 	if filters.get("item_code"):
 		conditions.append("item.name=%(item_code)s")
 	else:
-		if filters.get("brand"):
-			conditions.append("item.brand=%(brand)s")
 		if filters.get("item_group"):
 			conditions.append(get_item_group_condition(filters.get("item_group")))
 
diff --git a/erpnext/stock/report/stock_ledger/stock_ledger.js b/erpnext/stock/report/stock_ledger/stock_ledger.js
index 9adfbf7..6f12c27 100644
--- a/erpnext/stock/report/stock_ledger/stock_ledger.js
+++ b/erpnext/stock/report/stock_ledger/stock_ledger.js
@@ -32,7 +32,7 @@
 			"options": "Warehouse",
 			"get_query": function() {
 				const company = frappe.query_report.get_filter_value('company');
-				return { 
+				return {
 					filters: { 'company': company }
 				}
 			}
@@ -82,6 +82,11 @@
 			"label": __("Include UOM"),
 			"fieldtype": "Link",
 			"options": "UOM"
+		},
+		{
+			"fieldname": "show_cancelled_entries",
+			"label": __("Show Cancelled Entries"),
+			"fieldtype": "Check"
 		}
 	],
 	"formatter": function (value, row, column, data, default_formatter) {
@@ -96,9 +101,3 @@
 		return value;
 	},
 }
-
-// $(function() {
-// 	$(wrapper).bind("show", function() {
-// 		frappe.query_report.load();
-// 	});
-// });
\ No newline at end of file
diff --git a/erpnext/stock/report/stock_ledger/stock_ledger.py b/erpnext/stock/report/stock_ledger/stock_ledger.py
index 28d7208..abf959e 100644
--- a/erpnext/stock/report/stock_ledger/stock_ledger.py
+++ b/erpnext/stock/report/stock_ledger/stock_ledger.py
@@ -46,19 +46,6 @@
 			"out_qty": min(sle.actual_qty, 0)
 		})
 
-		# get the name of the item that was produced using this item
-		if sle.voucher_type == "Stock Entry":
-			purpose, work_order, fg_completed_qty = frappe.db.get_value(sle.voucher_type, sle.voucher_no, ["purpose", "work_order", "fg_completed_qty"])
-
-			if purpose == "Manufacture" and work_order:
-				finished_product = frappe.db.get_value("Work Order", work_order, "item_name")
-				finished_qty = fg_completed_qty
-
-				sle.update({
-					"finished_product": finished_product,
-					"finished_qty": finished_qty,
-				})
-
 		data.append(sle)
 
 		if include_uom:
@@ -77,8 +64,6 @@
 		{"label": _("In Qty"), "fieldname": "in_qty", "fieldtype": "Float", "width": 80, "convertible": "qty"},
 		{"label": _("Out Qty"), "fieldname": "out_qty", "fieldtype": "Float", "width": 80, "convertible": "qty"},
 		{"label": _("Balance Qty"), "fieldname": "qty_after_transaction", "fieldtype": "Float", "width": 100, "convertible": "qty"},
-		{"label": _("Finished Product"), "fieldname": "finished_product", "width": 100},
-		{"label": _("Finished Qty"), "fieldname": "finished_qty", "fieldtype": "Float", "width": 100, "convertible": "qty"},
 		{"label": _("Voucher #"), "fieldname": "voucher_no", "fieldtype": "Dynamic Link", "options": "voucher_type", "width": 150},
 		{"label": _("Warehouse"), "fieldname": "warehouse", "fieldtype": "Link", "options": "Warehouse", "width": 150},
 		{"label": _("Item Group"), "fieldname": "item_group", "fieldtype": "Link", "options": "Item Group", "width": 100},
@@ -196,6 +181,9 @@
 	if filters.get("project"):
 		conditions.append("project=%(project)s")
 
+	if not filters.get("show_cancelled_entries"):
+		conditions.append("is_cancelled = 0")
+
 	return "and {}".format(" and ".join(conditions)) if conditions else ""
 
 
diff --git a/erpnext/stock/stock_balance.py b/erpnext/stock/stock_balance.py
index 5697315..b5ae1b7 100644
--- a/erpnext/stock/stock_balance.py
+++ b/erpnext/stock/stock_balance.py
@@ -6,7 +6,6 @@
 from frappe.utils import flt, cstr, nowdate, nowtime
 from erpnext.stock.utils import update_bin
 from erpnext.stock.stock_ledger import update_entries_after
-from erpnext.controllers.stock_controller import update_gl_entries_after
 
 def repost(only_actual=False, allow_negative_stock=False, allow_zero_rate=False, only_bin=False):
 	"""
@@ -56,12 +55,13 @@
 
 		update_bin_qty(item_code, warehouse, qty_dict)
 
-def repost_actual_qty(item_code, warehouse, allow_zero_rate=False, allow_negative_stock=False):		update_entries_after({ "item_code": item_code, "warehouse": warehouse },
+def repost_actual_qty(item_code, warehouse, allow_zero_rate=False, allow_negative_stock=False):
+	update_entries_after({ "item_code": item_code, "warehouse": warehouse },
 		allow_zero_rate=allow_zero_rate, allow_negative_stock=allow_negative_stock)
 
 def get_balance_qty_from_sle(item_code, warehouse):
 	balance_qty = frappe.db.sql("""select qty_after_transaction from `tabStock Ledger Entry`
-		where item_code=%s and warehouse=%s and is_cancelled='No'
+		where item_code=%s and warehouse=%s
 		order by posting_date desc, posting_time desc, creation desc
 		limit 1""", (item_code, warehouse))
 
@@ -191,7 +191,7 @@
 			print(d[0], d[1], d[2], serial_nos[0][0])
 
 		sle = frappe.db.sql("""select valuation_rate, company from `tabStock Ledger Entry`
-			where item_code = %s and warehouse = %s and ifnull(is_cancelled, 'No') = 'No'
+			where item_code = %s and warehouse = %s
 			order by posting_date desc limit 1""", (d[0], d[1]))
 
 		sle_dict = {
@@ -208,7 +208,6 @@
 			'stock_uom'					: d[3],
 			'incoming_rate'				: sle and flt(serial_nos[0][0]) > flt(d[2]) and flt(sle[0][0]) or 0,
 			'company'					: sle and cstr(sle[0][1]) or 0,
-			'is_cancelled'			 	: 'No',
 			'batch_no'					: '',
 			'serial_no'					: ''
 		}
@@ -220,8 +219,7 @@
 
 		args = sle_dict.copy()
 		args.update({
-			"sle_id": sle_doc.name,
-			"is_amended": 'No'
+			"sle_id": sle_doc.name
 		})
 
 		update_bin(args)
@@ -246,15 +244,3 @@
 				sr.save()
 			except:
 				pass
-
-def repost_gle_for_stock_transactions(posting_date=None, posting_time=None, for_warehouses=None):
-	frappe.db.auto_commit_on_many_writes = 1
-
-	if not posting_date:
-		posting_date = "1900-01-01"
-	if not posting_time:
-		posting_time = "00:00"
-
-	update_gl_entries_after(posting_date, posting_time, for_warehouses=for_warehouses)
-
-	frappe.db.auto_commit_on_many_writes = 0
diff --git a/erpnext/stock/stock_ledger.py b/erpnext/stock/stock_ledger.py
index 7567a1a..b4cb8ca 100644
--- a/erpnext/stock/stock_ledger.py
+++ b/erpnext/stock/stock_ledger.py
@@ -4,8 +4,8 @@
 
 import frappe, erpnext
 from frappe import _
-from frappe.utils import cint, flt, cstr, now
-from erpnext.stock.utils import get_valuation_method
+from frappe.utils import cint, flt, cstr, now, now_datetime
+from erpnext.stock.utils import get_valuation_method, get_incoming_outgoing_rate_for_cancel
 import json
 
 from six import iteritems
@@ -16,36 +16,48 @@
 _exceptions = frappe.local('stockledger_exceptions')
 # _exceptions = []
 
-def make_sl_entries(sl_entries, is_amended=None, allow_negative_stock=False, via_landed_cost_voucher=False):
+def make_sl_entries(sl_entries, allow_negative_stock=False, via_landed_cost_voucher=False):
 	if sl_entries:
 		from erpnext.stock.utils import update_bin
 
-		cancel = True if sl_entries[0].get("is_cancelled") == "Yes" else False
+		cancel = sl_entries[0].get("is_cancelled")
 		if cancel:
-			set_as_cancel(sl_entries[0].get('voucher_no'), sl_entries[0].get('voucher_type'))
+			set_as_cancel(sl_entries[0].get('voucher_type'), sl_entries[0].get('voucher_no'))
 
 		for sle in sl_entries:
 			sle_id = None
-			if sle.get('is_cancelled') == 'Yes':
-				sle['actual_qty'] = -flt(sle['actual_qty'])
+			if via_landed_cost_voucher or cancel:
+				sle['posting_date'] = now_datetime().strftime('%Y-%m-%d')
+				sle['posting_time'] = now_datetime().strftime('%H:%M:%S.%f')
+
+				if cancel:
+					sle['actual_qty'] = -flt(sle.get('actual_qty'), 0)
+
+					if sle['actual_qty'] < 0 and not sle.get('outgoing_rate'):
+						sle['outgoing_rate'] = get_incoming_outgoing_rate_for_cancel(sle.item_code,
+							sle.voucher_type, sle.voucher_no, sle.voucher_detail_no)
+						sle['incoming_rate'] = 0.0
+
+					if sle['actual_qty'] > 0 and not sle.get('incoming_rate'):
+						sle['incoming_rate'] = get_incoming_outgoing_rate_for_cancel(sle.item_code,
+							sle.voucher_type, sle.voucher_no, sle.voucher_detail_no)
+						sle['outgoing_rate'] = 0.0
+
 
 			if sle.get("actual_qty") or sle.get("voucher_type")=="Stock Reconciliation":
 				sle_id = make_entry(sle, allow_negative_stock, via_landed_cost_voucher)
 
 			args = sle.copy()
 			args.update({
-				"sle_id": sle_id,
-				"is_amended": is_amended
+				"sle_id": sle_id
 			})
 			update_bin(args, allow_negative_stock, via_landed_cost_voucher)
 
-		if cancel:
-			delete_cancelled_entry(sl_entries[0].get('voucher_type'), sl_entries[0].get('voucher_no'))
 
 def set_as_cancel(voucher_type, voucher_no):
-	frappe.db.sql("""update `tabStock Ledger Entry` set is_cancelled='Yes',
+	frappe.db.sql("""update `tabStock Ledger Entry` set is_cancelled=1,
 		modified=%s, modified_by=%s
-		where voucher_no=%s and voucher_type=%s""",
+		where voucher_type=%s and voucher_no=%s and is_cancelled = 0""",
 		(now(), frappe.session.user, voucher_type, voucher_no))
 
 def make_entry(args, allow_negative_stock=False, via_landed_cost_voucher=False):
@@ -58,9 +70,6 @@
 	sle.submit()
 	return sle.name
 
-def delete_cancelled_entry(voucher_type, voucher_no):
-	frappe.db.sql("""delete from `tabStock Ledger Entry`
-		where voucher_type=%s and voucher_no=%s""", (voucher_type, voucher_no))
 
 class update_entries_after(object):
 	"""
@@ -106,14 +115,17 @@
 		self.stock_queue = json.loads(self.previous_sle.stock_queue or "[]")
 		self.valuation_method = get_valuation_method(self.item_code)
 		self.stock_value_difference = 0.0
-		self.build()
+		self.build(args.get('sle_id'))
 
-	def build(self):
-		# includes current entry!
-		entries_to_fix = self.get_sle_after_datetime()
-
-		for sle in entries_to_fix:
+	def build(self, sle_id):
+		if sle_id:
+			sle = get_sle_by_id(sle_id)
 			self.process_sle(sle)
+		else:
+			# includes current entry!
+			entries_to_fix = self.get_sle_after_datetime()
+			for sle in entries_to_fix:
+				self.process_sle(sle)
 
 		if self.exceptions:
 			self.raise_exceptions()
@@ -403,7 +415,10 @@
 
 	def get_sle_before_datetime(self):
 		"""get previous stock ledger entry before current time-bucket"""
-		return get_stock_ledger_entries(self.args, "<", "desc", "limit 1", for_update=False)
+		if self.args.get('sle_id'):
+			self.args['name'] = self.args.get('sle_id')
+
+		return get_stock_ledger_entries(self.args, "<=", "desc", "limit 1", for_update=False)
 
 	def get_sle_after_datetime(self):
 		"""get Stock Ledger Entries after a particular datetime, for reposting"""
@@ -470,9 +485,10 @@
 	if operator in (">", "<=") and previous_sle.get("name"):
 		conditions += " and name!=%(name)s"
 
-	return frappe.db.sql("""select *, timestamp(posting_date, posting_time) as "timestamp" from `tabStock Ledger Entry`
+	return frappe.db.sql("""
+		select *, timestamp(posting_date, posting_time) as "timestamp"
+		from `tabStock Ledger Entry`
 		where item_code = %%(item_code)s
-		and ifnull(is_cancelled, 'No')='No'
 		%(conditions)s
 		order by timestamp(posting_date, posting_time) %(order)s, creation %(order)s
 		%(limit)s %(for_update)s""" % {
@@ -482,6 +498,11 @@
 			"order": order
 		}, previous_sle, as_dict=1, debug=debug)
 
+def get_sle_by_id(sle_id):
+	return frappe.db.get_all('Stock Ledger Entry',
+		fields=['*', 'timestamp(posting_date, posting_time) as timestamp'],
+		filters={'name': sle_id})[0]
+
 def get_valuation_rate(item_code, warehouse, voucher_type, voucher_no,
 	allow_zero_rate=False, currency=None, company=None, raise_error_if_no_rate=True):
 	# Get valuation rate from last sle for the same item and warehouse
diff --git a/erpnext/stock/utils.py b/erpnext/stock/utils.py
index 7f32b8d..f21dc3f 100644
--- a/erpnext/stock/utils.py
+++ b/erpnext/stock/utils.py
@@ -364,4 +364,16 @@
 			else:
 				row[data.converted_col] = flt(value_before_conversion) / conversion_factor
 
-		result[row_idx] = row
\ No newline at end of file
+		result[row_idx] = row
+
+def get_incoming_outgoing_rate_for_cancel(item_code, voucher_type, voucher_no, voucher_detail_no):
+	outgoing_rate = frappe.db.sql("""SELECT abs(stock_value_difference / actual_qty)
+		FROM `tabStock Ledger Entry`
+		WHERE voucher_type = %s and voucher_no = %s
+			and item_code = %s and voucher_detail_no = %s
+			ORDER BY CREATION DESC limit 1""",
+		(voucher_type, voucher_no, item_code, voucher_detail_no))
+
+	outgoing_rate = outgoing_rate[0][0] if outgoing_rate else 0.0
+
+	return outgoing_rate
\ No newline at end of file
diff --git a/erpnext/utilities/transaction_base.py b/erpnext/utilities/transaction_base.py
index 14674c0..ea96503 100644
--- a/erpnext/utilities/transaction_base.py
+++ b/erpnext/utilities/transaction_base.py
@@ -5,8 +5,9 @@
 import frappe
 import frappe.share
 from frappe import _
-from frappe.utils import cstr, now_datetime, cint, flt, get_time, get_link_to_form
+from frappe.utils import cstr, now_datetime, cint, flt, get_time, get_datetime, get_link_to_form
 from erpnext.controllers.status_updater import StatusUpdater
+from erpnext.accounts.utils import get_fiscal_year
 
 from six import string_types
 
@@ -28,6 +29,8 @@
 			except ValueError:
 				frappe.throw(_('Invalid Posting Time'))
 
+		self.validate_with_last_transaction_posting_time()
+
 	def add_calendar_event(self, opts, force=False):
 		if cstr(self.contact_by) != cstr(self._prev.contact_by) or \
 				cstr(self.contact_date) != cstr(self._prev.contact_date) or force or \
@@ -148,6 +151,30 @@
 
 		return ret
 
+	def validate_with_last_transaction_posting_time(self):
+
+		if self.doctype not in ["Sales Invoice", "Purchase Invoice", "Stock Entry", "Stock Reconciliation",
+			"Delivery Note", "Purchase Receipt", "Fees"]:
+				return
+
+		if self.doctype in ["Sales Invoice", "Purchase Invoice"]:
+			if not (self.get("update_stock") or self.get("is_pos")):
+				return
+
+		fiscal_year = get_fiscal_year(self.get('posting_date'), as_dict=True).name
+
+		last_transaction_time = frappe.db.sql("""
+			select MAX(timestamp(posting_date, posting_time)) as posting_time
+			from `tabStock Ledger Entry`
+			where docstatus = 1 and fiscal_year = %s""", (fiscal_year))[0][0]
+
+		cur_doc_posting_datetime = "%s %s" % (self.posting_date, self.get("posting_time") or "00:00:00")
+
+		if last_transaction_time and get_datetime(cur_doc_posting_datetime) < get_datetime(last_transaction_time):
+			frappe.throw(_("""Posting timestamp of current transaction
+				must be after last Stock transaction's timestamp which is {0}""").format(frappe.bold(last_transaction_time)),
+				title=_("Backdated Stock Entry"))
+
 def delete_events(ref_type, ref_name):
 	events = frappe.db.sql_list(""" SELECT
 			distinct `tabEvent`.name
diff --git a/requirements.txt b/requirements.txt
index c277545..9da537e 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -8,3 +8,4 @@
 python-stdnum==1.12
 Unidecode==1.1.1
 WooCommerce==2.1.1
+tweepy==3.8.0
\ No newline at end of file