Merge branch 'develop' into fix-payment-entry-wrong-bank-account-fetch-develop
diff --git a/erpnext/accounts/accounts_dashboard/accounts/accounts.json b/erpnext/accounts/accounts_dashboard/accounts/accounts.json
new file mode 100644
index 0000000..2fab50e
--- /dev/null
+++ b/erpnext/accounts/accounts_dashboard/accounts/accounts.json
@@ -0,0 +1,58 @@
+{
+ "cards": [
+  {
+   "card": "Total Outgoing Bills"
+  },
+  {
+   "card": "Total Incoming Bills"
+  },
+  {
+   "card": "Total Incoming Payment"
+  },
+  {
+   "card": "Total Outgoing Payment"
+  }
+ ],
+ "charts": [
+  {
+   "chart": "Profit and Loss",
+   "width": "Full"
+  },
+  {
+   "chart": "Incoming Bills (Purchase Invoice)",
+   "width": "Half"
+  },
+  {
+   "chart": "Outgoing Bills (Sales Invoice)",
+   "width": "Half"
+  },
+  {
+   "chart": "Accounts Receivable Ageing",
+   "width": "Half"
+  },
+  {
+   "chart": "Accounts Payable Ageing",
+   "width": "Half"
+  },
+  {
+   "chart": "Budget Variance",
+   "width": "Full"
+  },
+  {
+   "chart": "Bank Balance",
+   "width": "Full"
+  }
+ ],
+ "creation": "2020-07-17 11:25:34.796608",
+ "dashboard_name": "Accounts",
+ "docstatus": 0,
+ "doctype": "Dashboard",
+ "idx": 0,
+ "is_default": 0,
+ "is_standard": 1,
+ "modified": "2020-07-22 13:07:34.540574",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "Accounts",
+ "owner": "Administrator"
+}
\ No newline at end of file
diff --git a/erpnext/accounts/dashboard_chart/accounts_payable_ageing/accounts_payable_ageing.json b/erpnext/accounts/dashboard_chart/accounts_payable_ageing/accounts_payable_ageing.json
new file mode 100644
index 0000000..fb5ee64
--- /dev/null
+++ b/erpnext/accounts/dashboard_chart/accounts_payable_ageing/accounts_payable_ageing.json
@@ -0,0 +1,23 @@
+{
+ "chart_name": "Accounts Payable Ageing",
+ "chart_type": "Report",
+ "creation": "2020-07-17 11:25:34.564015",
+ "docstatus": 0,
+ "doctype": "Dashboard Chart",
+ "dynamic_filters_json": "{\"company\":\"frappe.defaults.get_user_default(\\\"Company\\\")\",\"report_date\":\"frappe.datetime.now_date()\"}",
+ "filters_json": "{\"ageing_based_on\":\"Due Date\",\"range1\":30,\"range2\":60,\"range3\":90,\"range4\":120,\"group_by_party\":0,\"based_on_payment_terms\":0}",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "modified": "2020-07-22 12:29:33.584419",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "Accounts Payable Ageing",
+ "number_of_groups": 0,
+ "owner": "Administrator",
+ "report_name": "Accounts Payable",
+ "timeseries": 0,
+ "type": "Donut",
+ "use_report_chart": 1,
+ "y_axis": []
+}
\ No newline at end of file
diff --git a/erpnext/accounts/dashboard_chart/accounts_receivable_ageing/accounts_receivable_ageing.json b/erpnext/accounts/dashboard_chart/accounts_receivable_ageing/accounts_receivable_ageing.json
new file mode 100644
index 0000000..48ec781
--- /dev/null
+++ b/erpnext/accounts/dashboard_chart/accounts_receivable_ageing/accounts_receivable_ageing.json
@@ -0,0 +1,23 @@
+{
+ "chart_name": "Accounts Receivable Ageing",
+ "chart_type": "Report",
+ "creation": "2020-07-17 11:25:34.535388",
+ "docstatus": 0,
+ "doctype": "Dashboard Chart",
+ "dynamic_filters_json": "{\"company\":\"frappe.defaults.get_user_default(\\\"Company\\\")\",\"report_date\":\"frappe.datetime.now_date()\"}",
+ "filters_json": "{\"ageing_based_on\":\"Due Date\",\"range1\":30,\"range2\":60,\"range3\":90,\"range4\":120,\"group_by_party\":0,\"based_on_payment_terms\":0,\"show_future_payments\":0,\"show_delivery_notes\":0,\"show_sales_person\":0}",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "modified": "2020-07-22 12:28:42.743551",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "Accounts Receivable Ageing",
+ "number_of_groups": 0,
+ "owner": "Administrator",
+ "report_name": "Accounts Receivable",
+ "timeseries": 0,
+ "type": "Donut",
+ "use_report_chart": 1,
+ "y_axis": []
+}
\ No newline at end of file
diff --git a/erpnext/accounts/dashboard_chart/bank_balance/bank_balance.json b/erpnext/accounts/dashboard_chart/bank_balance/bank_balance.json
new file mode 100644
index 0000000..6442c02
--- /dev/null
+++ b/erpnext/accounts/dashboard_chart/bank_balance/bank_balance.json
@@ -0,0 +1,26 @@
+{
+ "chart_name": "Bank Balance",
+ "chart_type": "Custom",
+ "creation": "2020-07-17 11:25:34.620221",
+ "docstatus": 0,
+ "doctype": "Dashboard Chart",
+ "dynamic_filters_json": "{\"company\":\"frappe.defaults.get_user_default(\\\"Company\\\")\",\"account\":\"locals[\\\":Company\\\"][frappe.defaults.get_user_default(\\\"Company\\\")][\\\"default_bank_account\\\"]\"}",
+ "filters_json": "{}",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "last_synced_on": "2020-07-22 12:19:59.879476",
+ "modified": "2020-07-22 12:21:48.780513",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "Bank Balance",
+ "number_of_groups": 0,
+ "owner": "Administrator",
+ "source": "Account Balance Timeline",
+ "time_interval": "Quarterly",
+ "timeseries": 0,
+ "timespan": "Last Year",
+ "type": "Line",
+ "use_report_chart": 0,
+ "y_axis": []
+}
\ No newline at end of file
diff --git a/erpnext/accounts/dashboard_chart/budget_variance/budget_variance.json b/erpnext/accounts/dashboard_chart/budget_variance/budget_variance.json
new file mode 100644
index 0000000..8631d3d
--- /dev/null
+++ b/erpnext/accounts/dashboard_chart/budget_variance/budget_variance.json
@@ -0,0 +1,23 @@
+{
+ "chart_name": "Budget Variance",
+ "chart_type": "Report",
+ "creation": "2020-07-17 11:25:34.593061",
+ "docstatus": 0,
+ "doctype": "Dashboard Chart",
+ "dynamic_filters_json": "{\"company\":\"frappe.defaults.get_user_default(\\\"Company\\\")\",\"from_fiscal_year\":\"frappe.sys_defaults.fiscal_year\",\"to_fiscal_year\":\"frappe.sys_defaults.fiscal_year\"}",
+ "filters_json": "{\"period\":\"Monthly\",\"budget_against\":\"Cost Center\",\"show_cumulative\":0}",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "modified": "2020-07-22 12:24:49.144210",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "Budget Variance",
+ "number_of_groups": 0,
+ "owner": "Administrator",
+ "report_name": "Budget Variance Report",
+ "timeseries": 0,
+ "type": "Bar",
+ "use_report_chart": 1,
+ "y_axis": []
+}
\ No newline at end of file
diff --git "a/erpnext/accounts/dashboard_chart/incoming_bills_\050purchase_invoice\051/incoming_bills_\050purchase_invoice\051.json" "b/erpnext/accounts/dashboard_chart/incoming_bills_\050purchase_invoice\051/incoming_bills_\050purchase_invoice\051.json"
new file mode 100644
index 0000000..55f0d77
--- /dev/null
+++ "b/erpnext/accounts/dashboard_chart/incoming_bills_\050purchase_invoice\051/incoming_bills_\050purchase_invoice\051.json"
@@ -0,0 +1,29 @@
+{
+ "based_on": "posting_date",
+ "chart_name": "Incoming Bills (Purchase Invoice)",
+ "chart_type": "Sum",
+ "color": "#a83333",
+ "creation": "2020-07-17 11:25:34.479703",
+ "docstatus": 0,
+ "doctype": "Dashboard Chart",
+ "document_type": "Purchase Invoice",
+ "dynamic_filters_json": "",
+ "filters_json": "[[\"Purchase Invoice\",\"docstatus\",\"=\",1]]",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "last_synced_on": "2020-07-21 17:37:30.727306",
+ "modified": "2020-07-21 17:51:07.374917",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "Incoming Bills (Purchase Invoice)",
+ "number_of_groups": 0,
+ "owner": "Administrator",
+ "time_interval": "Monthly",
+ "timeseries": 1,
+ "timespan": "Last Year",
+ "type": "Bar",
+ "use_report_chart": 0,
+ "value_based_on": "base_net_total",
+ "y_axis": []
+}
\ No newline at end of file
diff --git "a/erpnext/accounts/dashboard_chart/outgoing_bills_\050sales_invoice\051/outgoing_bills_\050sales_invoice\051.json" "b/erpnext/accounts/dashboard_chart/outgoing_bills_\050sales_invoice\051/outgoing_bills_\050sales_invoice\051.json"
new file mode 100644
index 0000000..45de667
--- /dev/null
+++ "b/erpnext/accounts/dashboard_chart/outgoing_bills_\050sales_invoice\051/outgoing_bills_\050sales_invoice\051.json"
@@ -0,0 +1,28 @@
+{
+ "based_on": "posting_date",
+ "chart_name": "Outgoing Bills (Sales Invoice)",
+ "chart_type": "Sum",
+ "color": "#7b933d",
+ "creation": "2020-07-17 11:25:34.507547",
+ "docstatus": 0,
+ "doctype": "Dashboard Chart",
+ "document_type": "Sales Invoice",
+ "filters_json": "[[\"Sales Invoice\",\"docstatus\",\"=\",1]]",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "last_synced_on": "2020-07-21 17:37:31.574666",
+ "modified": "2020-07-21 17:52:03.970530",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "Outgoing Bills (Sales Invoice)",
+ "number_of_groups": 0,
+ "owner": "Administrator",
+ "time_interval": "Monthly",
+ "timeseries": 1,
+ "timespan": "Last Year",
+ "type": "Bar",
+ "use_report_chart": 0,
+ "value_based_on": "base_net_total",
+ "y_axis": []
+}
\ No newline at end of file
diff --git a/erpnext/accounts/dashboard_chart/profit_and_loss/profit_and_loss.json b/erpnext/accounts/dashboard_chart/profit_and_loss/profit_and_loss.json
new file mode 100644
index 0000000..3fa995b
--- /dev/null
+++ b/erpnext/accounts/dashboard_chart/profit_and_loss/profit_and_loss.json
@@ -0,0 +1,23 @@
+{
+ "chart_name": "Profit and Loss",
+ "chart_type": "Report",
+ "creation": "2020-07-17 11:25:34.448572",
+ "docstatus": 0,
+ "doctype": "Dashboard Chart",
+ "dynamic_filters_json": "{\"company\":\"frappe.defaults.get_user_default(\\\"Company\\\")\",\"from_fiscal_year\":\"frappe.sys_defaults.fiscal_year\",\"to_fiscal_year\":\"frappe.sys_defaults.fiscal_year\"}",
+ "filters_json": "{\"filter_based_on\":\"Fiscal Year\",\"period_start_date\":\"2020-04-01\",\"period_end_date\":\"2021-03-31\",\"periodicity\":\"Yearly\",\"include_default_book_entries\":1}",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "modified": "2020-07-22 12:33:48.888943",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "Profit and Loss",
+ "number_of_groups": 0,
+ "owner": "Administrator",
+ "report_name": "Profit and Loss Statement",
+ "timeseries": 0,
+ "type": "Bar",
+ "use_report_chart": 1,
+ "y_axis": []
+}
\ No newline at end of file
diff --git a/erpnext/accounts/dashboard_fixtures.py b/erpnext/accounts/dashboard_fixtures.py
deleted file mode 100644
index b2abffc..0000000
--- a/erpnext/accounts/dashboard_fixtures.py
+++ /dev/null
@@ -1,284 +0,0 @@
-# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-import frappe
-import json
-from frappe.utils import nowdate, add_months, get_date_str
-from frappe import _
-from erpnext.accounts.utils import get_fiscal_year, get_account_name, FiscalYearError
-
-def _get_fiscal_year(date=None):
-	try:
-		fiscal_year = get_fiscal_year(date=nowdate(), as_dict=True)
-		return fiscal_year
-
-	except FiscalYearError:
-		#if no fiscal year for current date then get default fiscal year
-		try:
-			fiscal_year = get_fiscal_year(as_dict=True)
-			return fiscal_year
-
-		except FiscalYearError:
-			#if still no fiscal year found then no accounting data created, return
-			return None
-
-def get_company_for_dashboards():
-	company = frappe.defaults.get_defaults().company
-	if company:
-		return company
-	else:
-		company_list = frappe.get_list("Company")
-		if company_list:
-			return company_list[0].name
-	return None
-
-def get_data():
-
-	fiscal_year = _get_fiscal_year(nowdate())
-
-	if not fiscal_year:
-		return frappe._dict()
-
-	return frappe._dict({
-		"dashboards": get_dashboards(),
-		"charts": get_charts(fiscal_year),
-		"number_cards": get_number_cards(fiscal_year)
-	})
-
-def get_dashboards():
-	return [{
-		"name": "Accounts",
-		"dashboard_name": "Accounts",
-		"doctype": "Dashboard",
-		"charts": [
-			{ "chart": "Profit and Loss" , "width": "Full"},
-			{ "chart": "Incoming Bills (Purchase Invoice)", "width": "Half"},
-			{ "chart": "Outgoing Bills (Sales Invoice)", "width": "Half"},
-			{ "chart": "Accounts Receivable Ageing", "width": "Half"},
-			{ "chart": "Accounts Payable Ageing", "width": "Half"},
-			{ "chart": "Budget Variance", "width": "Full"},
-			{ "chart": "Bank Balance", "width": "Full"}
-		],
-		"cards": [
-			{"card": "Total Outgoing Bills"},
-			{"card": "Total Incoming Bills"},
-			{"card": "Total Incoming Payment"},
-			{"card": "Total Outgoing Payment"}
-		]
-	}]
-
-def get_charts(fiscal_year):
-	company = frappe.get_doc("Company", get_company_for_dashboards())
-	bank_account = company.default_bank_account or get_account_name("Bank", company=company.name)
-	default_cost_center = company.cost_center
-
-	return [
-		{
-			"doctype": "Dashboard Charts",
-			"name": "Profit and Loss",
-			"owner": "Administrator",
-			"report_name": "Profit and Loss Statement",
-			"filters_json": json.dumps({
-				"company": company.name,
-				"filter_based_on": "Fiscal Year",
-				"from_fiscal_year": fiscal_year.get('name'),
-				"to_fiscal_year": fiscal_year.get('name'),
-				"periodicity": "Monthly",
-				"include_default_book_entries": 1
-			}),
-			"type": "Bar",
-			'timeseries': 0,
-			"chart_type": "Report",
-			"chart_name": _("Profit and Loss"),
-			"is_custom": 1,
-			"is_public": 1
-		},
-		{
-			"doctype": "Dashboard Chart",
-			"time_interval": "Monthly",
-			"name": "Incoming Bills (Purchase Invoice)",
-			"chart_name": _("Incoming Bills (Purchase Invoice)"),
-			"timespan": "Last Year",
-			"color": "#a83333",
-			"value_based_on": "base_net_total",
-			"filters_json": json.dumps([["Purchase Invoice", "docstatus", "=", 1]]),
-			"chart_type": "Sum",
-			"timeseries": 1,
-			"based_on": "posting_date",
-			"owner": "Administrator",
-			"document_type": "Purchase Invoice",
-			"type": "Bar",
-			"width": "Half",
-			"is_public": 1
-		},
-		{
-			"doctype": "Dashboard Chart",
-			"name": "Outgoing Bills (Sales Invoice)",
-			"time_interval": "Monthly",
-			"chart_name": _("Outgoing Bills (Sales Invoice)"),
-			"timespan": "Last Year",
-			"color": "#7b933d",
-			"value_based_on": "base_net_total",
-			"filters_json": json.dumps([["Sales Invoice", "docstatus", "=", 1]]),
-			"chart_type": "Sum",
-			"timeseries": 1,
-			"based_on": "posting_date",
-			"owner": "Administrator",
-			"document_type": "Sales Invoice",
-			"type": "Bar",
-			"width": "Half",
-			"is_public": 1
-		},
-		{
-			"doctype": "Dashboard Charts",
-			"name": "Accounts Receivable Ageing",
-			"owner": "Administrator",
-			"report_name": "Accounts Receivable",
-			"filters_json": json.dumps({
-				"company": company.name,
-				"report_date": nowdate(),
-				"ageing_based_on": "Due Date",
-				"range1": 30,
-				"range2": 60,
-				"range3": 90,
-				"range4": 120
-				}),
-			"type": "Donut",
-			'timeseries': 0,
-			"chart_type": "Report",
-			"chart_name": _("Accounts Receivable Ageing"),
-			"is_custom": 1,
-			"is_public": 1
-		},
-		{
-			"doctype": "Dashboard Charts",
-			"name": "Accounts Payable Ageing",
-			"owner": "Administrator",
-			"report_name": "Accounts Payable",
-			"filters_json": json.dumps({
-				"company": company.name,
-				"report_date": nowdate(),
-				"ageing_based_on": "Due Date",
-				"range1": 30,
-				"range2": 60,
-				"range3": 90,
-				"range4": 120
-			}),
-			"type": "Donut",
-			'timeseries': 0,
-			"chart_type": "Report",
-			"chart_name": _("Accounts Payable Ageing"),
-			"is_custom": 1,
-			"is_public": 1
-		},
-		{
-			"doctype": "Dashboard Charts",
-			"name": "Budget Variance",
-			"owner": "Administrator",
-			"report_name": "Budget Variance Report",
-			"filters_json": json.dumps({
-				"company": company.name,
-				"from_fiscal_year": fiscal_year.get('name'),
-				"to_fiscal_year": fiscal_year.get('name'),
-				"period": "Monthly",
-				"budget_against": "Cost Center"
-			}),
-			"type": "Bar",
-			"timeseries": 0,
-			"chart_type": "Report",
-			"chart_name": _("Budget Variance"),
-			"is_custom": 1,
-			"is_public": 1
-		},
-		{
-			"doctype": "Dashboard Charts",
-			"name": "Bank Balance",
-			"time_interval": "Quarterly",
-			"chart_name": "Bank Balance",
-			"timespan": "Last Year",
-			"filters_json": json.dumps({
-				"company": company.name,
-				"account": bank_account
-			}),
-			"source": "Account Balance Timeline",
-			"chart_type": "Custom",
-			"timeseries": 1,
-			"owner": "Administrator",
-			"type": "Line",
-			"width": "Half",
-			"is_public": 1
-		},
-	]
-
-def get_number_cards(fiscal_year):
-
-	year_start_date = get_date_str(fiscal_year.get("year_start_date"))
-	year_end_date = get_date_str(fiscal_year.get("year_end_date"))
-	return [
-		{
-			"doctype": "Number Card",
-			"document_type": "Payment Entry",
-			"name": "Total Incoming Payment",
-			"filters_json": json.dumps([
-				['Payment Entry', 'docstatus', '=', 1],
-				['Payment Entry', 'posting_date', 'between', [year_start_date, year_end_date]],
-				['Payment Entry', 'payment_type', '=', 'Receive']
-			]),
-			"label": _("Total Incoming Payment"),
-			"function": "Sum",
-			"aggregate_function_based_on": "base_received_amount",
-			"is_public": 1,
-			"is_custom": 1,
-			"show_percentage_stats": 1,
-			"stats_time_interval": "Monthly"
-		},
-		{
-			"doctype": "Number Card",
-			"document_type": "Payment Entry",
-			"name": "Total Outgoing Payment",
-			"filters_json": json.dumps([
-				['Payment Entry', 'docstatus', '=', 1],
-				['Payment Entry', 'posting_date', 'between', [year_start_date, year_end_date]],
-				['Payment Entry', 'payment_type', '=', 'Pay']
-			]),
-			"label": _("Total Outgoing Payment"),
-			"function": "Sum",
-			"aggregate_function_based_on": "base_paid_amount",
-			"is_public": 1,
-			"is_custom": 1,
-			"show_percentage_stats": 1,
-			"stats_time_interval": "Monthly"
-		},
-		{
-			"doctype": "Number Card",
-			"document_type": "Sales Invoice",
-			"name": "Total Outgoing Bills",
-			"filters_json": json.dumps([
-				['Sales Invoice', 'docstatus', '=', 1],
-				['Sales Invoice', 'posting_date', 'between', [year_start_date, year_end_date]]
-			]),
-			"label": _("Total Outgoing Bills"),
-			"function": "Sum",
-			"aggregate_function_based_on": "base_net_total",
-			"is_public": 1,
-			"is_custom": 1,
-			"show_percentage_stats": 1,
-			"stats_time_interval": "Monthly"
-		},
-		{
-			"doctype": "Number Card",
-			"document_type": "Purchase Invoice",
-			"name": "Total Incoming Bills",
-			"filters_json": json.dumps([
-				['Purchase Invoice', 'docstatus', '=', 1],
-				['Purchase Invoice', 'posting_date', 'between', [year_start_date, year_end_date]]
-			]),
-			"label": _("Total Incoming Bills"),
-			"function": "Sum",
-			"aggregate_function_based_on": "base_net_total",
-			"is_public": 1,
-			"is_custom": 1,
-			"show_percentage_stats": 1,
-			"stats_time_interval": "Monthly"
-		}
-	]
diff --git a/erpnext/accounts/deferred_revenue.py b/erpnext/accounts/deferred_revenue.py
index 4480110..d5ab1c1 100644
--- a/erpnext/accounts/deferred_revenue.py
+++ b/erpnext/accounts/deferred_revenue.py
@@ -2,10 +2,11 @@
 
 import frappe
 from frappe import _
-from frappe.utils import date_diff, add_months, today, getdate, add_days, flt, get_last_day, cint, get_link_to_form
+from frappe.utils import date_diff, add_months, today, getdate, add_days, flt, get_last_day, get_first_day, cint, get_link_to_form, rounded
 from erpnext.accounts.utils import get_account_currency
 from frappe.email import sendmail_to_system_managers
 from frappe.utils.background_jobs import enqueue
+from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_accounting_dimensions
 
 def validate_service_stop_date(doc):
 	''' Validates service_stop_date for Purchase Invoice and Sales Invoice '''
@@ -109,6 +110,18 @@
 		order by posting_date desc limit 1
 	''', (doc.company, item.get(deferred_account), doc.doctype, doc.name, item.name), as_dict=True)
 
+	prev_gl_via_je = frappe.db.sql('''
+		SELECT p.name, p.posting_date FROM `tabJournal Entry` p, `tabJournal Entry Account` c
+		WHERE p.name = c.parent and p.company=%s and c.account=%s
+		and c.reference_type=%s and c.reference_name=%s
+		and c.reference_detail_no=%s and c.docstatus < 2 order by posting_date desc limit 1
+	''', (doc.company, item.get(deferred_account), doc.doctype, doc.name, item.name), as_dict=True)
+
+	if prev_gl_via_je:
+		if (not prev_gl_entry) or (prev_gl_entry and
+			prev_gl_entry[0].posting_date < prev_gl_via_je[0].posting_date):
+			prev_gl_entry = prev_gl_via_je
+
 	if prev_gl_entry:
 		start_date = getdate(add_days(prev_gl_entry[0].posting_date, 1))
 	else:
@@ -130,14 +143,48 @@
 	else:
 		return None, None, None
 
-def calculate_amount(doc, item, last_gl_entry, total_days, total_booking_days, account_currency):
-	if doc.doctype == "Sales Invoice":
-		total_credit_debit, total_credit_debit_currency = "debit", "debit_in_account_currency"
-		deferred_account = "deferred_revenue_account"
-	else:
-		total_credit_debit, total_credit_debit_currency = "credit", "credit_in_account_currency"
-		deferred_account = "deferred_expense_account"
+def calculate_monthly_amount(doc, item, last_gl_entry, start_date, end_date, total_days, total_booking_days, account_currency):
+	amount, base_amount = 0, 0
 
+	if not last_gl_entry:
+		total_months = (item.service_end_date.year - item.service_start_date.year) * 12 + \
+			(item.service_end_date.month - item.service_start_date.month) + 1
+
+		prorate_factor = flt(date_diff(item.service_end_date, item.service_start_date)) \
+			/ flt(date_diff(get_last_day(item.service_end_date), get_first_day(item.service_start_date)))
+
+		actual_months = rounded(total_months * prorate_factor, 1)
+
+		already_booked_amount, already_booked_amount_in_account_currency = get_already_booked_amount(doc, item)
+		base_amount = flt(item.base_net_amount / actual_months, item.precision("base_net_amount"))
+
+		if base_amount + already_booked_amount > item.base_net_amount:
+			base_amount = item.base_net_amount - already_booked_amount
+
+		if account_currency==doc.company_currency:
+			amount = base_amount
+		else:
+			amount = flt(item.net_amount/actual_months, item.precision("net_amount"))
+			if amount + already_booked_amount_in_account_currency > item.net_amount:
+				amount = item.net_amount - already_booked_amount_in_account_currency
+
+		if not (get_first_day(start_date) == start_date and get_last_day(end_date) == end_date):
+			partial_month = flt(date_diff(end_date, start_date)) \
+				/ flt(date_diff(get_last_day(end_date), get_first_day(start_date)))
+
+			base_amount = rounded(partial_month, 1) * base_amount
+			amount = rounded(partial_month, 1) * amount
+	else:
+		already_booked_amount, already_booked_amount_in_account_currency = get_already_booked_amount(doc, item)
+		base_amount = flt(item.base_net_amount - already_booked_amount, item.precision("base_net_amount"))
+		if account_currency==doc.company_currency:
+			amount = base_amount
+		else:
+			amount = flt(item.net_amount - already_booked_amount_in_account_currency, item.precision("net_amount"))
+
+	return amount, base_amount
+
+def calculate_amount(doc, item, last_gl_entry, total_days, total_booking_days, account_currency):
 	amount, base_amount = 0, 0
 	if not last_gl_entry:
 		base_amount = flt(item.base_net_amount*total_booking_days/flt(total_days), item.precision("base_net_amount"))
@@ -146,27 +193,55 @@
 		else:
 			amount = flt(item.net_amount*total_booking_days/flt(total_days), item.precision("net_amount"))
 	else:
-		gl_entries_details = frappe.db.sql('''
-			select sum({0}) as total_credit, sum({1}) as total_credit_in_account_currency, voucher_detail_no
-			from `tabGL Entry` where company=%s and account=%s and voucher_type=%s and voucher_no=%s and voucher_detail_no=%s
-			group by voucher_detail_no
-		'''.format(total_credit_debit, total_credit_debit_currency),
-			(doc.company, item.get(deferred_account), doc.doctype, doc.name, item.name), as_dict=True)
-		already_booked_amount = gl_entries_details[0].total_credit if gl_entries_details else 0
+		already_booked_amount, already_booked_amount_in_account_currency = get_already_booked_amount(doc, item)
+
 		base_amount = flt(item.base_net_amount - already_booked_amount, item.precision("base_net_amount"))
 		if account_currency==doc.company_currency:
 			amount = base_amount
 		else:
-			already_booked_amount_in_account_currency = gl_entries_details[0].total_credit_in_account_currency if gl_entries_details else 0
 			amount = flt(item.net_amount - already_booked_amount_in_account_currency, item.precision("net_amount"))
 
 	return amount, base_amount
 
+def get_already_booked_amount(doc, item):
+	if doc.doctype == "Sales Invoice":
+		total_credit_debit, total_credit_debit_currency = "debit", "debit_in_account_currency"
+		deferred_account = "deferred_revenue_account"
+	else:
+		total_credit_debit, total_credit_debit_currency = "credit", "credit_in_account_currency"
+		deferred_account = "deferred_expense_account"
+
+	gl_entries_details = frappe.db.sql('''
+		select sum({0}) as total_credit, sum({1}) as total_credit_in_account_currency, voucher_detail_no
+		from `tabGL Entry` where company=%s and account=%s and voucher_type=%s and voucher_no=%s and voucher_detail_no=%s
+		group by voucher_detail_no
+	'''.format(total_credit_debit, total_credit_debit_currency),
+		(doc.company, item.get(deferred_account), doc.doctype, doc.name, item.name), as_dict=True)
+
+	journal_entry_details = frappe.db.sql('''
+		SELECT sum(c.{0}) as total_credit, sum(c.{1}) as total_credit_in_account_currency, reference_detail_no
+		FROM `tabJournal Entry` p , `tabJournal Entry Account` c WHERE p.name = c.parent and
+		p.company = %s and c.account=%s and c.reference_type=%s and c.reference_name=%s and c.reference_detail_no=%s
+		and p.docstatus < 2 group by reference_detail_no
+	'''.format(total_credit_debit, total_credit_debit_currency),
+		(doc.company, item.get(deferred_account), doc.doctype, doc.name, item.name), as_dict=True)
+
+	already_booked_amount = gl_entries_details[0].total_credit if gl_entries_details else 0
+	already_booked_amount += journal_entry_details[0].total_credit if journal_entry_details else 0
+
+	if doc.currency == doc.company_currency:
+		already_booked_amount_in_account_currency = already_booked_amount
+	else:
+		already_booked_amount_in_account_currency = gl_entries_details[0].total_credit_in_account_currency if gl_entries_details else 0
+		already_booked_amount_in_account_currency += journal_entry_details[0].total_credit_in_account_currency if journal_entry_details else 0
+
+	return already_booked_amount, already_booked_amount_in_account_currency
+
 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"
 
-	def _book_deferred_revenue_or_expense(item):
+	def _book_deferred_revenue_or_expense(item, via_journal_entry, submit_journal_entry, book_deferred_entries_based_on):
 		start_date, end_date, last_gl_entry = get_booking_dates(doc, item, posting_date=posting_date)
 		if not (start_date and end_date): return
 
@@ -181,23 +256,34 @@
 		total_days = date_diff(item.service_end_date, item.service_start_date) + 1
 		total_booking_days = date_diff(end_date, start_date) + 1
 
-		amount, base_amount = calculate_amount(doc, item, last_gl_entry,
-			total_days, total_booking_days, account_currency)
+		if book_deferred_entries_based_on == 'Months':
+			amount, base_amount = calculate_monthly_amount(doc, item, last_gl_entry,
+				start_date, end_date, total_days, total_booking_days, account_currency)
+		else:
+			amount, base_amount = calculate_amount(doc, item, last_gl_entry,
+				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, deferred_process)
+		if via_journal_entry:
+			book_revenue_via_journal_entry(doc, credit_account, debit_account, against, amount,
+				base_amount, end_date, project, account_currency, item.cost_center, item, deferred_process, submit_journal_entry)
+		else:
+			make_gl_entries(doc, credit_account, debit_account, against,
+				amount, base_amount, end_date, project, account_currency, item.cost_center, item, 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)
+			_book_deferred_revenue_or_expense(item, via_journal_entry, submit_journal_entry, book_deferred_entries_based_on)
 
+	via_journal_entry = cint(frappe.db.get_singles_value('Accounts Settings', 'book_deferred_entries_via_journal_entry'))
+	submit_journal_entry = cint(frappe.db.get_singles_value('Accounts Settings', 'submit_journal_entries'))
+	book_deferred_entries_based_on = frappe.db.get_singles_value('Accounts Settings', 'book_deferred_entries_based_on')
 
 	for item in doc.get('items'):
 		if item.get(enable_check):
-			_book_deferred_revenue_or_expense(item)
+			_book_deferred_revenue_or_expense(item, via_journal_entry, submit_journal_entry, book_deferred_entries_based_on)
 
 def process_deferred_accounting(posting_date=None):
 	''' Converts deferred income/expense into income/expense
@@ -281,3 +367,83 @@
 		and submit manually after resolving errors
 	""").format(get_link_to_form('Process Deferred Accounting', deferred_process))
 	sendmail_to_system_managers(title, content)
+
+def book_revenue_via_journal_entry(doc, credit_account, debit_account, against,
+	amount, base_amount, posting_date, project, account_currency, cost_center, item,
+	deferred_process=None, submit='No'):
+
+	if amount == 0: return
+
+	journal_entry = frappe.new_doc('Journal Entry')
+	journal_entry.posting_date = posting_date
+	journal_entry.company = doc.company
+	journal_entry.voucher_type = 'Deferred Revenue' if doc.doctype == 'Sales Invoice' \
+		else 'Deferred Expense'
+
+	debit_entry = {
+		'account': credit_account,
+		'credit': base_amount,
+		'credit_in_account_currency': amount,
+		'party_type': 'Customer' if doc.doctype == 'Sales Invoice' else 'Supplier',
+		'party': against,
+		'account_currency': account_currency,
+		'reference_name': doc.name,
+		'reference_type': doc.doctype,
+		'reference_detail_no': item.name,
+		'cost_center': cost_center,
+		'project': project,
+	}
+
+	credit_entry = {
+		'account': debit_account,
+		'debit': base_amount,
+		'debit_in_account_currency': amount,
+		'party_type': 'Customer' if doc.doctype == 'Sales Invoice' else 'Supplier',
+		'party': against,
+		'account_currency': account_currency,
+		'reference_name': doc.name,
+		'reference_type': doc.doctype,
+		'reference_detail_no': item.name,
+		'cost_center': cost_center,
+		'project': project,
+	}
+
+	for dimension in get_accounting_dimensions():
+		debit_entry.update({
+			dimension: item.get(dimension)
+		})
+
+		credit_entry.update({
+			dimension: item.get(dimension)
+		})
+
+	journal_entry.append('accounts', debit_entry)
+	journal_entry.append('accounts', credit_entry)
+
+	try:
+		journal_entry.save()
+
+		if submit:
+			journal_entry.submit()
+	except:
+		frappe.db.rollback()
+		traceback = frappe.get_traceback()
+		frappe.log_error(message=traceback)
+
+		frappe.flags.deferred_accounting_error = True
+
+def get_deferred_booking_accounts(doctype, voucher_detail_no, dr_or_cr):
+
+	if doctype == 'Sales Invoice':
+		credit_account, debit_account = frappe.db.get_value('Sales Invoice Item', {'name': voucher_detail_no},
+			['income_account', 'deferred_revenue_account'])
+	else:
+		credit_account, debit_account = frappe.db.get_value('Purchase Invoice Item', {'name': voucher_detail_no},
+			['deferred_expense_account', 'expense_account'])
+
+	if dr_or_cr == 'Debit':
+		return debit_account
+	else:
+		return credit_account
+
+
diff --git a/erpnext/accounts/desk_page/accounting/accounting.json b/erpnext/accounts/desk_page/accounting/accounting.json
index 31315e4..a249783 100644
--- a/erpnext/accounts/desk_page/accounting/accounting.json
+++ b/erpnext/accounts/desk_page/accounting/accounting.json
@@ -148,9 +148,14 @@
    "type": "Report"
   },
   {
+   "label": "Point of Sale",
+   "link_to": "point-of-sale",
+   "type": "Page"
+  },
+  {
    "label": "Dashboard",
    "link_to": "Accounts",
    "type": "Dashboard"
   }
  ]
-}
\ No newline at end of file
+}
diff --git a/erpnext/accounts/doctype/account/account.json b/erpnext/accounts/doctype/account/account.json
index af252e6..d2659d4 100644
--- a/erpnext/accounts/doctype/account/account.json
+++ b/erpnext/accounts/doctype/account/account.json
@@ -34,11 +34,15 @@
   {
    "fieldname": "properties",
    "fieldtype": "Section Break",
-   "oldfieldtype": "Section Break"
+   "oldfieldtype": "Section Break",
+   "show_days": 1,
+   "show_seconds": 1
   },
   {
    "fieldname": "column_break0",
    "fieldtype": "Column Break",
+   "show_days": 1,
+   "show_seconds": 1,
    "width": "50%"
   },
   {
@@ -49,7 +53,9 @@
    "no_copy": 1,
    "oldfieldname": "account_name",
    "oldfieldtype": "Data",
-   "reqd": 1
+   "reqd": 1,
+   "show_days": 1,
+   "show_seconds": 1
   },
   {
    "fieldname": "account_number",
@@ -57,13 +63,17 @@
    "in_list_view": 1,
    "in_standard_filter": 1,
    "label": "Account Number",
-   "read_only": 1
+   "read_only": 1,
+   "show_days": 1,
+   "show_seconds": 1
   },
   {
    "default": "0",
    "fieldname": "is_group",
    "fieldtype": "Check",
-   "label": "Is Group"
+   "label": "Is Group",
+   "show_days": 1,
+   "show_seconds": 1
   },
   {
    "fieldname": "company",
@@ -75,7 +85,9 @@
    "options": "Company",
    "read_only": 1,
    "remember_last_selected_value": 1,
-   "reqd": 1
+   "reqd": 1,
+   "show_days": 1,
+   "show_seconds": 1
   },
   {
    "fieldname": "root_type",
@@ -83,7 +95,9 @@
    "in_standard_filter": 1,
    "label": "Root Type",
    "options": "\nAsset\nLiability\nIncome\nExpense\nEquity",
-   "read_only": 1
+   "read_only": 1,
+   "show_days": 1,
+   "show_seconds": 1
   },
   {
    "fieldname": "report_type",
@@ -91,24 +105,32 @@
    "in_standard_filter": 1,
    "label": "Report Type",
    "options": "\nBalance Sheet\nProfit and Loss",
-   "read_only": 1
+   "read_only": 1,
+   "show_days": 1,
+   "show_seconds": 1
   },
   {
    "depends_on": "eval:doc.is_group==0",
    "fieldname": "account_currency",
    "fieldtype": "Link",
    "label": "Currency",
-   "options": "Currency"
+   "options": "Currency",
+   "show_days": 1,
+   "show_seconds": 1
   },
   {
    "default": "0",
    "fieldname": "inter_company_account",
    "fieldtype": "Check",
-   "label": "Inter Company Account"
+   "label": "Inter Company Account",
+   "show_days": 1,
+   "show_seconds": 1
   },
   {
    "fieldname": "column_break1",
    "fieldtype": "Column Break",
+   "show_days": 1,
+   "show_seconds": 1,
    "width": "50%"
   },
   {
@@ -120,7 +142,9 @@
    "oldfieldtype": "Link",
    "options": "Account",
    "reqd": 1,
-   "search_index": 1
+   "search_index": 1,
+   "show_days": 1,
+   "show_seconds": 1
   },
   {
    "description": "Setting Account Type helps in selecting this Account in transactions.",
@@ -130,7 +154,9 @@
    "label": "Account Type",
    "oldfieldname": "account_type",
    "oldfieldtype": "Select",
-   "options": "\nAccumulated Depreciation\nAsset Received But Not Billed\nBank\nCash\nChargeable\nCapital Work in Progress\nCost of Goods Sold\nDepreciation\nEquity\nExpense Account\nExpenses Included In Asset Valuation\nExpenses Included In Valuation\nFixed Asset\nIncome Account\nPayable\nReceivable\nRound Off\nStock\nStock Adjustment\nStock Received But Not Billed\nTax\nTemporary"
+   "options": "\nAccumulated Depreciation\nAsset Received But Not Billed\nBank\nCash\nChargeable\nCapital Work in Progress\nCost of Goods Sold\nDepreciation\nEquity\nExpense Account\nExpenses Included In Asset Valuation\nExpenses Included In Valuation\nFixed Asset\nIncome Account\nPayable\nReceivable\nRound Off\nStock\nStock Adjustment\nStock Received But Not Billed\nService Received But Not Billed\nTax\nTemporary",
+   "show_days": 1,
+   "show_seconds": 1
   },
   {
    "description": "Rate at which this tax is applied",
@@ -138,7 +164,9 @@
    "fieldtype": "Float",
    "label": "Rate",
    "oldfieldname": "tax_rate",
-   "oldfieldtype": "Currency"
+   "oldfieldtype": "Currency",
+   "show_days": 1,
+   "show_seconds": 1
   },
   {
    "description": "If the account is frozen, entries are allowed to restricted users.",
@@ -147,13 +175,17 @@
    "label": "Frozen",
    "oldfieldname": "freeze_account",
    "oldfieldtype": "Select",
-   "options": "No\nYes"
+   "options": "No\nYes",
+   "show_days": 1,
+   "show_seconds": 1
   },
   {
    "fieldname": "balance_must_be",
    "fieldtype": "Select",
    "label": "Balance must be",
-   "options": "\nDebit\nCredit"
+   "options": "\nDebit\nCredit",
+   "show_days": 1,
+   "show_seconds": 1
   },
   {
    "fieldname": "lft",
@@ -162,7 +194,9 @@
    "label": "Lft",
    "print_hide": 1,
    "read_only": 1,
-   "search_index": 1
+   "search_index": 1,
+   "show_days": 1,
+   "show_seconds": 1
   },
   {
    "fieldname": "rgt",
@@ -171,7 +205,9 @@
    "label": "Rgt",
    "print_hide": 1,
    "read_only": 1,
-   "search_index": 1
+   "search_index": 1,
+   "show_days": 1,
+   "show_seconds": 1
   },
   {
    "fieldname": "old_parent",
@@ -179,27 +215,33 @@
    "hidden": 1,
    "label": "Old Parent",
    "print_hide": 1,
-   "read_only": 1
+   "read_only": 1,
+   "show_days": 1,
+   "show_seconds": 1
   },
   {
    "default": "0",
    "depends_on": "eval:(doc.report_type == 'Profit and Loss' && !doc.is_group)",
    "fieldname": "include_in_gross",
    "fieldtype": "Check",
-   "label": "Include in gross"
+   "label": "Include in gross",
+   "show_days": 1,
+   "show_seconds": 1
   },
   {
    "default": "0",
    "fieldname": "disabled",
    "fieldtype": "Check",
-   "label": "Disable"
+   "label": "Disable",
+   "show_days": 1,
+   "show_seconds": 1
   }
  ],
  "icon": "fa fa-money",
  "idx": 1,
  "is_tree": 1,
  "links": [],
- "modified": "2020-03-18 17:57:52.063233",
+ "modified": "2020-06-11 15:15:54.338622",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "Account",
diff --git a/erpnext/accounts/doctype/accounts_settings/accounts_settings.json b/erpnext/accounts/doctype/accounts_settings/accounts_settings.json
index 353ff77..8ca8b71 100644
--- a/erpnext/accounts/doctype/accounts_settings/accounts_settings.json
+++ b/erpnext/accounts/doctype/accounts_settings/accounts_settings.json
@@ -19,10 +19,14 @@
   "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",
+  "deferred_accounting_settings_section",
   "automatically_process_deferred_accounting_entry",
+  "book_deferred_entries_based_on",
+  "column_break_18",
+  "book_deferred_entries_via_journal_entry",
+  "submit_journal_entries",
   "print_settings",
   "show_inclusive_tax_in_print",
   "column_break_12",
@@ -109,12 +113,6 @@
    "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",
@@ -189,13 +187,45 @@
    "fieldname": "automatically_process_deferred_accounting_entry",
    "fieldtype": "Check",
    "label": "Automatically Process Deferred Accounting Entry"
+  },
+  {
+   "fieldname": "deferred_accounting_settings_section",
+   "fieldtype": "Section Break",
+   "label": "Deferred Accounting Settings"
+  },
+  {
+   "fieldname": "column_break_18",
+   "fieldtype": "Column Break"
+  },
+  {
+   "default": "0",
+   "description": "If this is unchecked direct GL Entries will be created to book Deferred Revenue/Expense",
+   "fieldname": "book_deferred_entries_via_journal_entry",
+   "fieldtype": "Check",
+   "label": "Book Deferred Entries Via Journal Entry"
+  },
+  {
+   "default": "0",
+   "depends_on": "eval:doc.book_deferred_entries_via_journal_entry",
+   "description": "If this is unchecked Journal Entries will be saved in a Draft state and will have to be submitted manually",
+   "fieldname": "submit_journal_entries",
+   "fieldtype": "Check",
+   "label": "Submit Journal Entries"
+  },
+  {
+   "default": "Days",
+   "description": "If \"Months\" is selected then fixed amount will be booked as deferred revenue or expense for each month irrespective of number of days in a month. Will be prorated if deferred revenue or expense is not booked for an entire month.",
+   "fieldname": "book_deferred_entries_based_on",
+   "fieldtype": "Select",
+   "label": "Book Deferred Entries Based On",
+   "options": "Days\nMonths"
   }
  ],
  "icon": "icon-cog",
  "idx": 1,
  "issingle": 1,
  "links": [],
- "modified": "2019-12-19 16:58:17.395595",
+ "modified": "2020-06-22 20:13:26.043092",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "Accounts Settings",
diff --git a/erpnext/accounts/doctype/accounts_settings/accounts_settings.py b/erpnext/accounts/doctype/accounts_settings/accounts_settings.py
index 2473d71..5593466 100644
--- a/erpnext/accounts/doctype/accounts_settings/accounts_settings.py
+++ b/erpnext/accounts/doctype/accounts_settings/accounts_settings.py
@@ -20,7 +20,6 @@
 
 		self.validate_stale_days()
 		self.enable_payment_schedule_in_print()
-		self.enable_fields_for_cost_center_settings()
 
 	def validate_stale_days(self):
 		if not self.allow_stale and cint(self.stale_days) <= 0:
@@ -33,8 +32,3 @@
 		for doctype in ("Sales Order", "Sales Invoice", "Purchase Order", "Purchase Invoice"):
 			make_property_setter(doctype, "due_date", "print_hide", show_in_print, "Check")
 			make_property_setter(doctype, "payment_schedule", "print_hide",  0 if show_in_print else 1, "Check")
-
-	def enable_fields_for_cost_center_settings(self):
-		show_field = 0 if cint(self.allow_cost_center_in_entry_of_bs_account) else 1
-		for doctype in ("Sales Invoice", "Purchase Invoice", "Payment Entry"):
-			make_property_setter(doctype, "cost_center", "hidden", show_field, "Check")
diff --git a/erpnext/accounts/doctype/bank/bank.json b/erpnext/accounts/doctype/bank/bank.json
index 99978e6..56bae72 100644
--- a/erpnext/accounts/doctype/bank/bank.json
+++ b/erpnext/accounts/doctype/bank/bank.json
@@ -13,7 +13,6 @@
   "bank_name",
   "swift_number",
   "column_break_1",
-  "branch_code",
   "website",
   "address_and_contact",
   "address_html",
@@ -52,15 +51,6 @@
    "search_index": 1
   },
   {
-   "allow_in_quick_entry": 1,
-   "fieldname": "branch_code",
-   "fieldtype": "Data",
-   "in_list_view": 1,
-   "in_standard_filter": 1,
-   "label": "Branch Code",
-   "unique": 1
-  },
-  {
    "fieldname": "address_and_contact",
    "fieldtype": "Section Break",
    "label": "Address and Contact",
@@ -111,7 +101,7 @@
   }
  ],
  "links": [],
- "modified": "2020-03-25 21:22:33.496264",
+ "modified": "2020-07-17 14:00:13.105433",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "Bank",
diff --git a/erpnext/accounts/doctype/bank_account/bank_account.json b/erpnext/accounts/doctype/bank_account/bank_account.json
index 65a0a51..b42f1f9 100644
--- a/erpnext/accounts/doctype/bank_account/bank_account.json
+++ b/erpnext/accounts/doctype/bank_account/bank_account.json
@@ -23,6 +23,7 @@
   "account_details_section",
   "iban",
   "column_break_12",
+  "branch_code",
   "bank_account_no",
   "address_and_contact",
   "address_html",
@@ -197,10 +198,16 @@
    "fieldtype": "Data",
    "label": "Mask",
    "read_only": 1
+  },
+  {
+   "fieldname": "branch_code",
+   "fieldtype": "Data",
+   "in_global_search": 1,
+   "label": "Branch Code"
   }
  ],
  "links": [],
- "modified": "2020-04-06 21:00:45.379804",
+ "modified": "2020-07-17 13:59:50.795412",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "Bank Account",
diff --git a/erpnext/accounts/doctype/bank_guarantee/bank_guarantee.js b/erpnext/accounts/doctype/bank_guarantee/bank_guarantee.js
index 065d25e..febf85c 100644
--- a/erpnext/accounts/doctype/bank_guarantee/bank_guarantee.js
+++ b/erpnext/accounts/doctype/bank_guarantee/bank_guarantee.js
@@ -4,7 +4,7 @@
 cur_frm.add_fetch('bank_account','account','account');
 cur_frm.add_fetch('bank_account','bank_account_no','bank_account_no');
 cur_frm.add_fetch('bank_account','iban','iban');
-cur_frm.add_fetch('bank','branch_code','branch_code');
+cur_frm.add_fetch('bank_account','branch_code','branch_code');
 cur_frm.add_fetch('bank','swift_number','swift_number');
 
 frappe.ui.form.on('Bank Guarantee', {
diff --git a/erpnext/accounts/page/pos/__init__.py b/erpnext/accounts/doctype/dunning/__init__.py
similarity index 100%
rename from erpnext/accounts/page/pos/__init__.py
rename to erpnext/accounts/doctype/dunning/__init__.py
diff --git a/erpnext/accounts/doctype/dunning/dunning.js b/erpnext/accounts/doctype/dunning/dunning.js
new file mode 100644
index 0000000..c563368
--- /dev/null
+++ b/erpnext/accounts/doctype/dunning/dunning.js
@@ -0,0 +1,149 @@
+// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+frappe.ui.form.on("Dunning", {
+	setup: function (frm) {
+		frm.set_query("sales_invoice", () => {
+			return {
+				filters: {
+					docstatus: 1,
+					company: frm.doc.company,
+					outstanding_amount: [">", 0],
+					status: "Overdue"
+				},
+			};
+		});
+		frm.set_query("income_account", () => {
+			return {
+				filters: {
+					company: frm.doc.company,
+					root_type: "Income",
+					is_group: 0
+				}
+			};
+		});
+	},
+	refresh: function (frm) {
+		frm.set_df_property("company", "read_only", frm.doc.__islocal ? 0 : 1);
+		frm.set_df_property(
+			"sales_invoice",
+			"read_only",
+			frm.doc.__islocal ? 0 : 1
+		);
+		if (frm.doc.docstatus === 1 && frm.doc.status === "Unresolved") {
+			frm.add_custom_button(__("Resolve"), () => {
+				frm.set_value("status", "Resolved");
+			});
+		}
+		if (frm.doc.docstatus === 1 && frm.doc.status !== "Resolved") {
+			frm.add_custom_button(
+				__("Payment"),
+				function () {
+					frm.events.make_payment_entry(frm);
+				},__("Create")
+			);
+			frm.page.set_inner_btn_group_as_primary(__("Create"));
+		}
+	},
+	overdue_days: function (frm) {
+		frappe.db.get_value(
+			"Dunning Type",
+			{
+				start_day: ["<", frm.doc.overdue_days],
+				end_day: [">=", frm.doc.overdue_days],
+			},
+			"dunning_type",
+			(r) => {
+				if (r) {
+					frm.set_value("dunning_type", r.dunning_type);
+				} else {
+					frm.set_value("dunning_type", "");
+					frm.set_value("rate_of_interest", "");
+					frm.set_value("dunning_fee", "");
+				}
+			}
+		);
+	},
+	dunning_type: function (frm) {
+		frm.trigger("get_dunning_letter_text");
+	},
+	language: function (frm) {
+		frm.trigger("get_dunning_letter_text");
+	},
+	get_dunning_letter_text: function (frm) {
+		if (frm.doc.dunning_type) {
+			frappe.call({
+				method:
+				"erpnext.accounts.doctype.dunning.dunning.get_dunning_letter_text",
+				args: {
+					dunning_type: frm.doc.dunning_type,
+					language: frm.doc.language,
+					doc: frm.doc,
+				},
+				callback: function (r) {
+					if (r.message) {
+						frm.set_value("body_text", r.message.body_text);
+						frm.set_value("closing_text", r.message.closing_text);
+						frm.set_value("language", r.message.language);
+					} else {
+						frm.set_value("body_text", "");
+						frm.set_value("closing_text", "");
+					}
+				},
+			});
+		}
+	},
+	due_date: function (frm) {
+		frm.trigger("calculate_overdue_days");
+	},
+	posting_date: function (frm) {
+		frm.trigger("calculate_overdue_days");
+	},
+	rate_of_interest: function (frm) {
+		frm.trigger("calculate_interest_and_amount");
+	},
+	outstanding_amount: function (frm) {
+		frm.trigger("calculate_interest_and_amount");
+	},
+	interest_amount: function (frm) {
+		frm.trigger("calculate_interest_and_amount");
+	},
+	dunning_fee: function (frm) {
+		frm.trigger("calculate_interest_and_amount");
+	},
+	sales_invoice: function (frm) {
+		frm.trigger("calculate_overdue_days");
+	},
+	calculate_overdue_days: function (frm) {
+		if (frm.doc.posting_date && frm.doc.due_date) {
+			const overdue_days = moment(frm.doc.posting_date).diff(
+				frm.doc.due_date,
+				"days"
+			);
+			frm.set_value("overdue_days", overdue_days);
+		}
+	},
+	calculate_interest_and_amount: function (frm) {
+		const interest_per_year = frm.doc.outstanding_amount * frm.doc.rate_of_interest / 100;
+		const interest_amount = interest_per_year / 365 * frm.doc.overdue_days || 0;
+		const dunning_amount = interest_amount + frm.doc.dunning_fee;
+		const grand_total = frm.doc.outstanding_amount + dunning_amount;
+		frm.set_value("interest_amount", interest_amount);
+		frm.set_value("dunning_amount", dunning_amount);
+		frm.set_value("grand_total", grand_total);
+	},
+	make_payment_entry: function (frm) {
+		return frappe.call({
+			method:
+			"erpnext.accounts.doctype.payment_entry.payment_entry.get_payment_entry",
+			args: {
+				dt: frm.doc.doctype,
+				dn: frm.doc.name,
+			},
+			callback: function (r) {
+				var doc = frappe.model.sync(r.message);
+				frappe.set_route("Form", doc[0].doctype, doc[0].name);
+			},
+		});
+	},
+});
diff --git a/erpnext/accounts/doctype/dunning/dunning.json b/erpnext/accounts/doctype/dunning/dunning.json
new file mode 100644
index 0000000..b3eddf5
--- /dev/null
+++ b/erpnext/accounts/doctype/dunning/dunning.json
@@ -0,0 +1,370 @@
+{
+ "actions": [],
+ "allow_events_in_timeline": 1,
+ "autoname": "naming_series:",
+ "creation": "2019-07-05 16:34:31.013238",
+ "doctype": "DocType",
+ "engine": "InnoDB",
+ "field_order": [
+  "title",
+  "naming_series",
+  "sales_invoice",
+  "customer",
+  "customer_name",
+  "outstanding_amount",
+  "currency",
+  "conversion_rate",
+  "column_break_3",
+  "company",
+  "posting_date",
+  "posting_time",
+  "due_date",
+  "overdue_days",
+  "address_and_contact_section",
+  "address_display",
+  "contact_display",
+  "contact_mobile",
+  "contact_email",
+  "column_break_18",
+  "company_address_display",
+  "section_break_6",
+  "dunning_type",
+  "interest_amount",
+  "column_break_8",
+  "rate_of_interest",
+  "dunning_fee",
+  "section_break_12",
+  "dunning_amount",
+  "grand_total",
+  "income_account",
+  "column_break_17",
+  "status",
+  "printing_setting_section",
+  "language",
+  "body_text",
+  "column_break_22",
+  "letter_head",
+  "closing_text",
+  "amended_from"
+ ],
+ "fields": [
+  {
+   "fieldname": "company",
+   "fieldtype": "Link",
+   "label": "Company",
+   "options": "Company",
+   "reqd": 1
+  },
+  {
+   "default": "DUNN-.MM.-.YY.-",
+   "fieldname": "naming_series",
+   "fieldtype": "Select",
+   "label": "Series",
+   "options": "DUNN-.MM.-.YY.-"
+  },
+  {
+   "fieldname": "sales_invoice",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "in_standard_filter": 1,
+   "label": "Sales Invoice",
+   "options": "Sales Invoice",
+   "reqd": 1
+  },
+  {
+   "fetch_from": "sales_invoice.customer_name",
+   "fieldname": "customer_name",
+   "fieldtype": "Data",
+   "in_list_view": 1,
+   "label": "Customer Name",
+   "read_only": 1
+  },
+  {
+   "fetch_from": "sales_invoice.outstanding_amount",
+   "fieldname": "outstanding_amount",
+   "fieldtype": "Currency",
+   "label": "Outstanding Amount",
+   "read_only": 1
+  },
+  {
+   "fieldname": "column_break_3",
+   "fieldtype": "Column Break"
+  },
+  {
+   "default": "Today",
+   "fieldname": "posting_date",
+   "fieldtype": "Date",
+   "label": "Date"
+  },
+  {
+   "fieldname": "overdue_days",
+   "fieldtype": "Int",
+   "label": "Overdue Days",
+   "read_only": 1
+  },
+  {
+   "fieldname": "section_break_6",
+   "fieldtype": "Section Break"
+  },
+  {
+   "fieldname": "dunning_type",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "in_standard_filter": 1,
+   "label": "Dunning Type",
+   "options": "Dunning Type",
+   "reqd": 1
+  },
+  {
+   "default": "0",
+   "fieldname": "interest_amount",
+   "fieldtype": "Currency",
+   "label": "Interest Amount",
+   "precision": "2",
+   "read_only": 1
+  },
+  {
+   "fieldname": "column_break_8",
+   "fieldtype": "Column Break"
+  },
+  {
+   "default": "0",
+   "fetch_from": "dunning_type.dunning_fee",
+   "fetch_if_empty": 1,
+   "fieldname": "dunning_fee",
+   "fieldtype": "Currency",
+   "label": "Dunning Fee",
+   "precision": "2"
+  },
+  {
+   "fieldname": "section_break_12",
+   "fieldtype": "Section Break"
+  },
+  {
+   "fieldname": "column_break_17",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "printing_setting_section",
+   "fieldtype": "Section Break",
+   "label": "Printing Setting"
+  },
+  {
+   "fieldname": "language",
+   "fieldtype": "Link",
+   "label": "Print Language",
+   "options": "Language"
+  },
+  {
+   "fieldname": "letter_head",
+   "fieldtype": "Link",
+   "label": "Letter Head",
+   "options": "Letter Head"
+  },
+  {
+   "fieldname": "column_break_22",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fetch_from": "sales_invoice.currency",
+   "fieldname": "currency",
+   "fieldtype": "Link",
+   "hidden": 1,
+   "label": "Currency",
+   "options": "Currency",
+   "read_only": 1
+  },
+  {
+   "fieldname": "amended_from",
+   "fieldtype": "Link",
+   "label": "Amended From",
+   "no_copy": 1,
+   "options": "Dunning",
+   "print_hide": 1,
+   "read_only": 1
+  },
+  {
+   "allow_on_submit": 1,
+   "default": "{customer_name}",
+   "fieldname": "title",
+   "fieldtype": "Data",
+   "hidden": 1,
+   "label": "Title"
+  },
+  {
+   "fieldname": "body_text",
+   "fieldtype": "Text Editor",
+   "label": "Body Text"
+  },
+  {
+   "fieldname": "closing_text",
+   "fieldtype": "Text Editor",
+   "label": "Closing Text"
+  },
+  {
+   "fetch_from": "sales_invoice.due_date",
+   "fieldname": "due_date",
+   "fieldtype": "Date",
+   "label": "Due Date",
+   "read_only": 1
+  },
+  {
+   "fieldname": "posting_time",
+   "fieldtype": "Time",
+   "label": "Posting Time"
+  },
+  {
+   "default": "0",
+   "fetch_from": "dunning_type.interest_rate",
+   "fetch_if_empty": 1,
+   "fieldname": "rate_of_interest",
+   "fieldtype": "Float",
+   "label": "Rate of Interest (%) Yearly"
+  },
+  {
+   "fieldname": "address_and_contact_section",
+   "fieldtype": "Section Break",
+   "label": "Address and Contact"
+  },
+  {
+   "fetch_from": "sales_invoice.address_display",
+   "fieldname": "address_display",
+   "fieldtype": "Small Text",
+   "label": "Address",
+   "read_only": 1
+  },
+  {
+   "fetch_from": "sales_invoice.contact_display",
+   "fieldname": "contact_display",
+   "fieldtype": "Small Text",
+   "label": "Contact",
+   "read_only": 1
+  },
+  {
+   "fetch_from": "sales_invoice.contact_mobile",
+   "fieldname": "contact_mobile",
+   "fieldtype": "Small Text",
+   "label": "Mobile No",
+   "read_only": 1
+  },
+  {
+   "fieldname": "column_break_18",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fetch_from": "sales_invoice.company_address_display",
+   "fieldname": "company_address_display",
+   "fieldtype": "Small Text",
+   "label": "Company Address",
+   "read_only": 1
+  },
+  {
+   "fetch_from": "sales_invoice.contact_email",
+   "fieldname": "contact_email",
+   "fieldtype": "Data",
+   "label": "Contact Email",
+   "options": "Email",
+   "read_only": 1
+  },
+  {
+   "fetch_from": "sales_invoice.customer",
+   "fieldname": "customer",
+   "fieldtype": "Link",
+   "label": "Customer",
+   "options": "Customer",
+   "read_only": 1
+  },
+  {
+   "default": "0",
+   "fieldname": "grand_total",
+   "fieldtype": "Currency",
+   "label": "Grand Total",
+   "precision": "2",
+   "read_only": 1
+  },
+  {
+   "allow_on_submit": 1,
+   "default": "Unresolved",
+   "fieldname": "status",
+   "fieldtype": "Select",
+   "in_standard_filter": 1,
+   "label": "Status",
+   "options": "Draft\nResolved\nUnresolved\nCancelled"
+  },
+  {
+   "fieldname": "dunning_amount",
+   "fieldtype": "Currency",
+   "hidden": 1,
+   "label": "Dunning Amount",
+   "read_only": 1
+  },
+  {
+   "fieldname": "income_account",
+   "fieldtype": "Link",
+   "label": "Income Account",
+   "options": "Account"
+  },
+  {
+   "fetch_from": "sales_invoice.conversion_rate",
+   "fieldname": "conversion_rate",
+   "fieldtype": "Float",
+   "hidden": 1,
+   "label": "Conversion Rate",
+   "read_only": 1
+  }
+ ],
+ "is_submittable": 1,
+ "links": [],
+ "modified": "2020-07-21 18:20:23.512151",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "Dunning",
+ "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
+  },
+  {
+   "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,
+   "write": 1
+  }
+ ],
+ "sort_field": "modified",
+ "sort_order": "ASC",
+ "title_field": "customer_name",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/dunning/dunning.py b/erpnext/accounts/doctype/dunning/dunning.py
new file mode 100644
index 0000000..0be6a48
--- /dev/null
+++ b/erpnext/accounts/doctype/dunning/dunning.py
@@ -0,0 +1,119 @@
+# -*- 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
+import json
+from six import string_types
+from frappe.utils import getdate, get_datetime, rounded, flt
+from erpnext.loan_management.doctype.loan_interest_accrual.loan_interest_accrual import days_in_year
+from erpnext.accounts.general_ledger import make_gl_entries, make_reverse_gl_entries
+from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_accounting_dimensions
+from erpnext.controllers.accounts_controller import AccountsController
+
+
+class Dunning(AccountsController):
+	def validate(self):
+		self.validate_overdue_days()
+		self.validate_amount()
+		if not self.income_account:
+			self.income_account = frappe.db.get_value('Company', self.company, 'default_income_account')
+
+	def validate_overdue_days(self):
+		self.overdue_days = (getdate(self.posting_date) - getdate(self.due_date)).days or 0
+
+	def validate_amount(self):
+		amounts = calculate_interest_and_amount(
+			self.posting_date, self.outstanding_amount, self.rate_of_interest, self.dunning_fee, self.overdue_days)
+		if self.interest_amount != amounts.get('interest_amount'):
+			self.interest_amount = amounts.get('interest_amount')
+		if self.dunning_amount != amounts.get('dunning_amount'):
+			self.dunning_amount = amounts.get('dunning_amount')
+		if self.grand_total != amounts.get('grand_total'):
+			self.grand_total = amounts.get('grand_total')
+
+	def on_submit(self):
+		self.make_gl_entries()
+
+	def on_cancel(self):
+		if self.dunning_amount:
+			self.ignore_linked_doctypes = ('GL Entry', 'Stock Ledger Entry')
+			make_reverse_gl_entries(voucher_type=self.doctype, voucher_no=self.name)
+
+	def make_gl_entries(self):
+		if not self.dunning_amount:
+			return
+		gl_entries = []
+		invoice_fields = ["project", "cost_center", "debit_to", "party_account_currency", "conversion_rate", "cost_center"]
+		inv = frappe.db.get_value("Sales Invoice", self.sales_invoice, invoice_fields, as_dict=1)
+		accounting_dimensions = get_accounting_dimensions()
+		invoice_fields.extend(accounting_dimensions)
+		dunning_in_company_currency = flt(self.dunning_amount * inv.conversion_rate)
+		default_cost_center = frappe.get_cached_value('Company',  self.company,  'cost_center')
+		gl_entries.append(
+			self.get_gl_dict({
+				"account": inv.debit_to,
+				"party_type": "Customer",
+				"party": self.customer,
+				"due_date": self.due_date,
+				"against": self.income_account,
+				"debit": dunning_in_company_currency,
+				"debit_in_account_currency": self.dunning_amount,
+				"against_voucher": self.name,
+				"against_voucher_type": "Dunning",
+				"cost_center": inv.cost_center or default_cost_center,
+				"project": inv.project
+			}, inv.party_account_currency, item=inv)
+		)
+		gl_entries.append(
+			self.get_gl_dict({
+				"account": self.income_account,
+				"against": self.customer,
+				"credit": dunning_in_company_currency,
+				"cost_center": inv.cost_center or default_cost_center,
+				"credit_in_account_currency": self.dunning_amount,
+				"project": inv.project
+			}, item=inv)
+		)
+		make_gl_entries(gl_entries, cancel=(self.docstatus == 2), update_outstanding="No", merge_entries=False)
+
+
+def resolve_dunning(doc, state):
+	for reference in doc.references:
+		if reference.reference_doctype == 'Sales Invoice' and reference.outstanding_amount <= 0:
+			dunnings = frappe.get_list('Dunning', filters={
+				'sales_invoice': reference.reference_name, 'status': ('!=', 'Resolved')})
+
+			for dunning in dunnings:
+				frappe.db.set_value("Dunning", dunning.name, "status", 'Resolved')
+
+def calculate_interest_and_amount(posting_date, outstanding_amount, rate_of_interest, dunning_fee, overdue_days):
+	interest_amount = 0
+	if rate_of_interest:
+		interest_per_year = rounded(flt(outstanding_amount) * flt(rate_of_interest))/100
+		interest_amount = (
+            interest_per_year / days_in_year(get_datetime(posting_date).year)) * int(overdue_days)
+		grand_total = flt(outstanding_amount) + flt(interest_amount) + flt(dunning_fee)
+	dunning_amount = flt(interest_amount) + flt(dunning_fee)
+	return {
+		'interest_amount': interest_amount,
+		'grand_total': grand_total,
+		'dunning_amount': dunning_amount}
+
+@frappe.whitelist()
+def get_dunning_letter_text(dunning_type, doc, language=None):
+	if isinstance(doc, string_types):
+		doc = json.loads(doc)
+	if language:
+		filters = {'parent': dunning_type, 'language': language}
+	else:
+		filters = {'parent': dunning_type, 'is_default_language': 1}
+	letter_text = frappe.db.get_value('Dunning Letter Text', filters,
+		['body_text', 'closing_text', 'language'], as_dict=1)
+	if letter_text:
+		return {
+			'body_text': frappe.render_template(letter_text.body_text, doc),
+			'closing_text': frappe.render_template(letter_text.closing_text, doc),
+			'language': letter_text.language
+		}
diff --git a/erpnext/accounts/doctype/dunning/dunning_list.js b/erpnext/accounts/doctype/dunning/dunning_list.js
new file mode 100644
index 0000000..8dc0a8c
--- /dev/null
+++ b/erpnext/accounts/doctype/dunning/dunning_list.js
@@ -0,0 +1,9 @@
+frappe.listview_settings["Dunning"] = {
+	get_indicator: function (doc) {
+		if (doc.status === "Resolved") {
+			return [__("Resolved"), "green", "status,=,Resolved"];
+		} else {
+			return [__("Unresolved"), "red", "status,=,Unresolved"];
+		}
+	},
+};
diff --git a/erpnext/accounts/doctype/dunning/test_dunning.py b/erpnext/accounts/doctype/dunning/test_dunning.py
new file mode 100644
index 0000000..cb18309
--- /dev/null
+++ b/erpnext/accounts/doctype/dunning/test_dunning.py
@@ -0,0 +1,100 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
+# See license.txt
+from __future__ import unicode_literals
+
+import frappe
+import unittest
+from frappe.utils import add_days, today, nowdate
+from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import unlink_payment_on_cancel_of_invoice
+from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice_against_cost_center
+from erpnext.accounts.doctype.dunning.dunning import calculate_interest_and_amount
+from erpnext.accounts.doctype.payment_entry.test_payment_entry import get_payment_entry
+
+
+class TestDunning(unittest.TestCase):
+	@classmethod
+	def setUpClass(self):
+		create_dunning_type()
+		unlink_payment_on_cancel_of_invoice()
+
+	@classmethod
+	def tearDownClass(self):
+		unlink_payment_on_cancel_of_invoice(0)
+
+	def test_dunning(self):
+		dunning = create_dunning()
+		amounts = calculate_interest_and_amount(
+			dunning.posting_date, dunning.outstanding_amount, dunning.rate_of_interest, dunning.dunning_fee, dunning.overdue_days)
+		self.assertEqual(round(amounts.get('interest_amount'), 2), 0.44)
+		self.assertEqual(round(amounts.get('dunning_amount'), 2), 20.44)
+		self.assertEqual(round(amounts.get('grand_total'), 2), 120.44)
+	
+	def test_gl_entries(self):
+		dunning = create_dunning()
+		dunning.submit()
+		gl_entries = frappe.db.sql("""select account, debit, credit
+			from `tabGL Entry` where voucher_type='Dunning' and voucher_no=%s
+			order by account asc""", dunning.name, as_dict=1)
+		self.assertTrue(gl_entries)
+		expected_values = dict((d[0], d) for d in [
+			['Debtors - _TC', 20.44, 0.0],
+			['Sales - _TC',  0.0, 20.44]
+		])
+		for gle in gl_entries:
+			self.assertEquals(expected_values[gle.account][0], gle.account)
+			self.assertEquals(expected_values[gle.account][1], gle.debit)
+			self.assertEquals(expected_values[gle.account][2], gle.credit)
+
+	def test_payment_entry(self):
+		dunning = create_dunning()
+		dunning.submit()
+		pe = get_payment_entry("Dunning", dunning.name)
+		pe.reference_no = "1"
+		pe.reference_date = nowdate()
+		pe.paid_from_account_currency = dunning.currency
+		pe.paid_to_account_currency = dunning.currency
+		pe.source_exchange_rate = 1
+		pe.target_exchange_rate = 1
+		pe.insert()
+		pe.submit()
+		si_doc = frappe.get_doc('Sales Invoice', dunning.sales_invoice)
+		self.assertEqual(si_doc.outstanding_amount, 0)
+
+
+def create_dunning():
+	posting_date = add_days(today(), -20)
+	due_date = add_days(today(), -15)
+	sales_invoice = create_sales_invoice_against_cost_center(
+		posting_date=posting_date, due_date=due_date, status='Overdue')
+	dunning_type = frappe.get_doc("Dunning Type", 'First Notice')
+	dunning = frappe.new_doc("Dunning")
+	dunning.sales_invoice = sales_invoice.name
+	dunning.customer_name = sales_invoice.customer_name
+	dunning.outstanding_amount = sales_invoice.outstanding_amount
+	dunning.debit_to = sales_invoice.debit_to
+	dunning.currency = sales_invoice.currency
+	dunning.company = sales_invoice.company
+	dunning.posting_date = nowdate()
+	dunning.due_date = sales_invoice.due_date
+	dunning.dunning_type = 'First Notice'
+	dunning.rate_of_interest = dunning_type.rate_of_interest
+	dunning.dunning_fee = dunning_type.dunning_fee
+	dunning.save()
+	return dunning
+
+def create_dunning_type():
+	dunning_type = frappe.new_doc("Dunning Type")
+	dunning_type.dunning_type = 'First Notice'
+	dunning_type.start_day = 10
+	dunning_type.end_day = 20
+	dunning_type.dunning_fee = 20
+	dunning_type.rate_of_interest = 8
+	dunning_type.append(
+		"dunning_letter_text", {
+			'language': 'en',
+			'body_text': 'We have still not received payment for our invoice ',
+			'closing_text': 'We kindly request that you pay the outstanding amount immediately, including interest and late fees.'
+		}
+	)
+	dunning_type.save()
diff --git a/erpnext/accounts/page/pos/__init__.py b/erpnext/accounts/doctype/dunning_letter_text/__init__.py
similarity index 100%
copy from erpnext/accounts/page/pos/__init__.py
copy to erpnext/accounts/doctype/dunning_letter_text/__init__.py
diff --git a/erpnext/accounts/doctype/dunning_letter_text/dunning_letter_text.json b/erpnext/accounts/doctype/dunning_letter_text/dunning_letter_text.json
new file mode 100644
index 0000000..5ede3a1
--- /dev/null
+++ b/erpnext/accounts/doctype/dunning_letter_text/dunning_letter_text.json
@@ -0,0 +1,70 @@
+{
+ "actions": [],
+ "creation": "2019-12-06 04:25:40.215625",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "language",
+  "is_default_language",
+  "section_break_4",
+  "body_text",
+  "closing_text",
+  "section_break_7",
+  "body_and_closing_text_help"
+ ],
+ "fields": [
+  {
+   "fieldname": "language",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "label": "Language",
+   "options": "Language"
+  },
+  {
+   "default": "0",
+   "fieldname": "is_default_language",
+   "fieldtype": "Check",
+   "label": "Is Default Language"
+  },
+  {
+   "fieldname": "section_break_4",
+   "fieldtype": "Section Break"
+  },
+  {
+   "description": "Letter or Email Body Text",
+   "fieldname": "body_text",
+   "fieldtype": "Text Editor",
+   "in_list_view": 1,
+   "label": "Body Text"
+  },
+  {
+   "description": "Letter or Email Closing Text",
+   "fieldname": "closing_text",
+   "fieldtype": "Text Editor",
+   "in_list_view": 1,
+   "label": "Closing Text"
+  },
+  {
+   "fieldname": "section_break_7",
+   "fieldtype": "Section Break"
+  },
+  {
+   "fieldname": "body_and_closing_text_help",
+   "fieldtype": "HTML",
+   "label": "Body and Closing Text Help",
+   "options": "<h4>Body Text and Closing Text Example</h4>\n\n<div>We have noticed that you have not yet paid invoice {{sales_invoice}} for {{frappe.db.get_value(\"Currency\", currency, \"symbol\")}} {{outstanding_amount}}. This is a friendly reminder that the invoice was due on {{due_date}}. Please pay the amount due immediately to avoid any further dunning cost.</div>\n\n<h4>How to get fieldnames</h4>\n\n<p>The fieldnames you can use in your template are the fields in the document. You can find out the fields of any documents via Setup &gt; Customize Form View and selecting the document type (e.g. Sales Invoice)</p>\n\n<h4>Templating</h4>\n\n<p>Templates are compiled using the Jinja Templating Language. To learn more about Jinja, <a class=\"strong\" href=\"http://jinja.pocoo.org/docs/dev/templates/\">read this documentation.</a></p>"
+  }
+ ],
+ "istable": 1,
+ "links": [],
+ "modified": "2020-07-14 18:02:35.988958",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "Dunning Letter Text",
+ "owner": "Administrator",
+ "permissions": [],
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/dunning_letter_text/dunning_letter_text.py b/erpnext/accounts/doctype/dunning_letter_text/dunning_letter_text.py
new file mode 100644
index 0000000..426497b
--- /dev/null
+++ b/erpnext/accounts/doctype/dunning_letter_text/dunning_letter_text.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 DunningLetterText(Document):
+	pass
diff --git a/erpnext/accounts/page/pos/__init__.py b/erpnext/accounts/doctype/dunning_type/__init__.py
similarity index 100%
copy from erpnext/accounts/page/pos/__init__.py
copy to erpnext/accounts/doctype/dunning_type/__init__.py
diff --git a/erpnext/accounts/doctype/dunning_type/dunning_type.js b/erpnext/accounts/doctype/dunning_type/dunning_type.js
new file mode 100644
index 0000000..54156b4
--- /dev/null
+++ b/erpnext/accounts/doctype/dunning_type/dunning_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('Dunning Type', {
+	// refresh: function(frm) {
+
+	// }
+});
diff --git a/erpnext/accounts/doctype/dunning_type/dunning_type.json b/erpnext/accounts/doctype/dunning_type/dunning_type.json
new file mode 100644
index 0000000..da43664
--- /dev/null
+++ b/erpnext/accounts/doctype/dunning_type/dunning_type.json
@@ -0,0 +1,129 @@
+{
+ "actions": [],
+ "allow_rename": 1,
+ "autoname": "field:dunning_type",
+ "creation": "2019-12-04 04:59:08.003664",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "dunning_type",
+  "overdue_interval_section",
+  "start_day",
+  "column_break_4",
+  "end_day",
+  "section_break_6",
+  "dunning_fee",
+  "column_break_8",
+  "rate_of_interest",
+  "text_block_section",
+  "dunning_letter_text"
+ ],
+ "fields": [
+  {
+   "fieldname": "dunning_type",
+   "fieldtype": "Data",
+   "in_list_view": 1,
+   "label": "Dunning Type",
+   "reqd": 1,
+   "unique": 1
+  },
+  {
+   "fieldname": "dunning_fee",
+   "fieldtype": "Currency",
+   "in_list_view": 1,
+   "label": "Dunning Fee"
+  },
+  {
+   "description": "This section allows the user to set the Body and Closing text of the Dunning Letter for the Dunning Type based on language, which can be used in Print.",
+   "fieldname": "text_block_section",
+   "fieldtype": "Section Break",
+   "label": "Dunning Letter"
+  },
+  {
+   "fieldname": "dunning_letter_text",
+   "fieldtype": "Table",
+   "options": "Dunning Letter Text"
+  },
+  {
+   "fieldname": "column_break_4",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "section_break_6",
+   "fieldtype": "Section Break"
+  },
+  {
+   "fieldname": "column_break_8",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "overdue_interval_section",
+   "fieldtype": "Section Break",
+   "label": "Overdue Interval"
+  },
+  {
+   "fieldname": "start_day",
+   "fieldtype": "Int",
+   "label": "Start Day"
+  },
+  {
+   "fieldname": "end_day",
+   "fieldtype": "Int",
+   "label": "End Day"
+  },
+  {
+   "fieldname": "rate_of_interest",
+   "fieldtype": "Float",
+   "in_list_view": 1,
+   "label": "Rate of Interest (%) Yearly"
+  }
+ ],
+ "links": [],
+ "modified": "2020-07-15 17:14:17.835074",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "Dunning 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": "Administrator",
+   "share": 1,
+   "write": 1
+  }
+ ],
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/selling/doctype/pos_closing_voucher_invoices/pos_closing_voucher_invoices.py b/erpnext/accounts/doctype/dunning_type/dunning_type.py
similarity index 60%
rename from erpnext/selling/doctype/pos_closing_voucher_invoices/pos_closing_voucher_invoices.py
rename to erpnext/accounts/doctype/dunning_type/dunning_type.py
index a2d488b..8708748 100644
--- a/erpnext/selling/doctype/pos_closing_voucher_invoices/pos_closing_voucher_invoices.py
+++ b/erpnext/accounts/doctype/dunning_type/dunning_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 POSClosingVoucherInvoices(Document):
+class DunningType(Document):
 	pass
diff --git a/erpnext/accounts/doctype/dunning_type/test_dunning_type.py b/erpnext/accounts/doctype/dunning_type/test_dunning_type.py
new file mode 100644
index 0000000..b2fb26f
--- /dev/null
+++ b/erpnext/accounts/doctype/dunning_type/test_dunning_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 TestDunningType(unittest.TestCase):
+	pass
diff --git a/erpnext/accounts/doctype/gl_entry/gl_entry.py b/erpnext/accounts/doctype/gl_entry/gl_entry.py
index 645da34..def9ed6 100644
--- a/erpnext/accounts/doctype/gl_entry/gl_entry.py
+++ b/erpnext/accounts/doctype/gl_entry/gl_entry.py
@@ -72,12 +72,6 @@
 			if not self.cost_center and self.voucher_type != 'Period Closing Voucher':
 				frappe.throw(_("{0} {1}: Cost Center is required for 'Profit and Loss' account {2}. Please set up a default Cost Center for the Company.")
 					.format(self.voucher_type, self.voucher_no, self.account))
-		else:
-			from erpnext.accounts.utils import get_allow_cost_center_in_entry_of_bs_account
-			if not get_allow_cost_center_in_entry_of_bs_account() and self.cost_center:
-				self.cost_center = None
-			if self.project:
-				self.project = None
 
 	def validate_dimensions_for_pl_and_bs(self):
 
diff --git a/erpnext/accounts/doctype/invoice_discounting/invoice_discounting.js b/erpnext/accounts/doctype/invoice_discounting/invoice_discounting.js
index 0fab8b7..db4f7c4 100644
--- a/erpnext/accounts/doctype/invoice_discounting/invoice_discounting.js
+++ b/erpnext/accounts/doctype/invoice_discounting/invoice_discounting.js
@@ -188,14 +188,15 @@
 	},
 
 	show_general_ledger: (frm) => {
-		if(frm.doc.docstatus===1) {
+		if(frm.doc.docstatus > 0) {
 			cur_frm.add_custom_button(__('Accounting Ledger'), function() {
 				frappe.route_options = {
 					voucher_no: frm.doc.name,
 					from_date: frm.doc.posting_date,
-					to_date: frm.doc.posting_date,
+					to_date: moment(frm.doc.modified).format('YYYY-MM-DD'),
 					company: frm.doc.company,
-					group_by: "Group by Voucher (Consolidated)"
+					group_by: "Group by Voucher (Consolidated)",
+					show_cancelled_entries: frm.doc.docstatus === 2
 				};
 				frappe.set_route("query-report", "General Ledger");
 			}, __("View"));
diff --git a/erpnext/accounts/doctype/invoice_discounting/invoice_discounting.py b/erpnext/accounts/doctype/invoice_discounting/invoice_discounting.py
index 594b4d4..8083b21 100644
--- a/erpnext/accounts/doctype/invoice_discounting/invoice_discounting.py
+++ b/erpnext/accounts/doctype/invoice_discounting/invoice_discounting.py
@@ -3,7 +3,7 @@
 # For license information, please see license.txt
 
 from __future__ import unicode_literals
-import frappe, json
+import frappe, json, erpnext
 from frappe import _
 from frappe.utils import flt, getdate, nowdate, add_days
 from erpnext.controllers.accounts_controller import AccountsController
@@ -134,16 +134,19 @@
 		je.append("accounts", {
 			"account": self.bank_account,
 			"debit_in_account_currency": flt(self.total_amount) - flt(self.bank_charges),
+			"cost_center": erpnext.get_default_cost_center(self.company)
 		})
 
 		je.append("accounts", {
 			"account": self.bank_charges_account,
-			"debit_in_account_currency": flt(self.bank_charges)
+			"debit_in_account_currency": flt(self.bank_charges),
+			"cost_center": erpnext.get_default_cost_center(self.company)
 		})
 
 		je.append("accounts", {
 			"account": self.short_term_loan,
 			"credit_in_account_currency": flt(self.total_amount),
+			"cost_center": erpnext.get_default_cost_center(self.company),
 			"reference_type": "Invoice Discounting",
 			"reference_name": self.name
 		})
@@ -151,6 +154,7 @@
 			je.append("accounts", {
 				"account": self.accounts_receivable_discounted,
 				"debit_in_account_currency": flt(d.outstanding_amount),
+				"cost_center": erpnext.get_default_cost_center(self.company),
 				"reference_type": "Invoice Discounting",
 				"reference_name": self.name,
 				"party_type": "Customer",
@@ -160,6 +164,7 @@
 			je.append("accounts", {
 				"account": self.accounts_receivable_credit,
 				"credit_in_account_currency": flt(d.outstanding_amount),
+				"cost_center": erpnext.get_default_cost_center(self.company),
 				"reference_type": "Invoice Discounting",
 				"reference_name": self.name,
 				"party_type": "Customer",
@@ -177,13 +182,15 @@
 		je.append("accounts", {
 			"account": self.short_term_loan,
 			"debit_in_account_currency": flt(self.total_amount),
+			"cost_center": erpnext.get_default_cost_center(self.company),
 			"reference_type": "Invoice Discounting",
 			"reference_name": self.name,
 		})
 
 		je.append("accounts", {
 			"account": self.bank_account,
-			"credit_in_account_currency": flt(self.total_amount)
+			"credit_in_account_currency": flt(self.total_amount),
+			"cost_center": erpnext.get_default_cost_center(self.company)
 		})
 
 		if getdate(self.loan_end_date) > getdate(nowdate()):
@@ -193,6 +200,7 @@
 					je.append("accounts", {
 						"account": self.accounts_receivable_discounted,
 						"credit_in_account_currency": flt(outstanding_amount),
+						"cost_center": erpnext.get_default_cost_center(self.company),
 						"reference_type": "Invoice Discounting",
 						"reference_name": self.name,
 						"party_type": "Customer",
@@ -202,6 +210,7 @@
 					je.append("accounts", {
 						"account": self.accounts_receivable_unpaid,
 						"debit_in_account_currency": flt(outstanding_amount),
+						"cost_center": erpnext.get_default_cost_center(self.company),
 						"reference_type": "Invoice Discounting",
 						"reference_name": self.name,
 						"party_type": "Customer",
diff --git a/erpnext/accounts/doctype/item_tax_template/item_tax_template.js b/erpnext/accounts/doctype/item_tax_template/item_tax_template.js
index 42abdb8..e921a0d 100644
--- a/erpnext/accounts/doctype/item_tax_template/item_tax_template.js
+++ b/erpnext/accounts/doctype/item_tax_template/item_tax_template.js
@@ -6,6 +6,18 @@
 		frm.set_query("tax_type", "taxes", function(doc) {
 			return {
 				filters: [
+					['Account', 'company', '=', frm.doc.company],
+					['Account', 'is_group', '=', 0],
+					['Account', 'account_type', 'in', ['Tax', 'Chargeable', 'Income Account', 'Expense Account', 'Expenses Included In Valuation']]
+				]
+			}
+		});
+	},
+	company: function (frm) {
+		frm.set_query("tax_type", "taxes", function(doc) {
+			return {
+				filters: [
+					['Account', 'company', '=', frm.doc.company],
 					['Account', 'is_group', '=', 0],
 					['Account', 'account_type', 'in', ['Tax', 'Chargeable', 'Income Account', 'Expense Account', 'Expenses Included In Valuation']]
 				]
diff --git a/erpnext/accounts/doctype/item_tax_template/item_tax_template.json b/erpnext/accounts/doctype/item_tax_template/item_tax_template.json
index f713cfc..856c371 100644
--- a/erpnext/accounts/doctype/item_tax_template/item_tax_template.json
+++ b/erpnext/accounts/doctype/item_tax_template/item_tax_template.json
@@ -1,168 +1,85 @@
 {
- "allow_copy": 0, 
- "allow_events_in_timeline": 0, 
- "allow_guest_to_view": 0, 
- "allow_import": 1, 
- "allow_rename": 1, 
- "autoname": "field:title", 
- "beta": 0, 
- "creation": "2018-11-22 22:45:00.370913", 
- "custom": 0, 
- "docstatus": 0, 
- "doctype": "DocType", 
- "document_type": "Setup", 
- "editable_grid": 1, 
- "engine": "InnoDB", 
+ "allow_import": 1,
+ "allow_rename": 1,
+ "autoname": "field:title",
+ "creation": "2018-11-22 22:45:00.370913",
+ "doctype": "DocType",
+ "document_type": "Setup",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "title",
+  "company",
+  "taxes"
+ ],
  "fields": [
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "title", 
-   "fieldtype": "Data", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 1, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Title", 
-   "length": 0, 
-   "no_copy": 1, 
-   "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, 
+   "fieldname": "title",
+   "fieldtype": "Data",
+   "in_filter": 1,
+   "in_list_view": 1,
+   "label": "Title",
+   "no_copy": 1,
+   "reqd": 1,
    "unique": 1
-  }, 
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "taxes", 
-   "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": "Tax Rates", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Item Tax 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, 
-   "translatable": 0, 
-   "unique": 0
+   "fieldname": "taxes",
+   "fieldtype": "Table",
+   "label": "Tax Rates",
+   "options": "Item Tax Template Detail",
+   "reqd": 1
+  },
+  {
+   "fieldname": "company",
+   "fieldtype": "Link",
+   "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": 0, 
- "max_attachments": 0, 
- "modified": "2018-12-21 23:51:16.328340", 
- "modified_by": "Administrator", 
- "module": "Accounts", 
- "name": "Item Tax Template", 
- "name_case": "", 
- "owner": "Administrator", 
+ ],
+ "modified": "2020-06-18 20:27:42.615842",
+ "modified_by": "ahmad@havenir.com",
+ "module": "Accounts",
+ "name": "Item Tax Template",
+ "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": "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
-  }, 
+  },
   {
-   "amend": 0, 
-   "cancel": 0, 
-   "create": 0, 
-   "delete": 0, 
-   "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": 0
+   "email": 1,
+   "export": 1,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "Accounts User",
+   "share": 1
   }
- ], 
- "quick_entry": 0, 
- "read_only": 0, 
- "read_only_onload": 0, 
- "search_fields": "", 
- "show_name_in_global_search": 1, 
- "sort_field": "modified", 
- "sort_order": "DESC", 
- "track_changes": 1, 
- "track_seen": 0, 
- "track_views": 0
+ ],
+ "show_name_in_global_search": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
 }
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/item_tax_template/test_records.json b/erpnext/accounts/doctype/item_tax_template/test_records.json
index db540e8..4d9537d 100644
--- a/erpnext/accounts/doctype/item_tax_template/test_records.json
+++ b/erpnext/accounts/doctype/item_tax_template/test_records.json
@@ -2,6 +2,7 @@
  {
   "doctype": "Item Tax Template",
   "title": "_Test Account Excise Duty @ 10",
+  "company": "_Test Company",
   "taxes": [
    {
     "doctype": "Item Tax Template Detail",
@@ -14,6 +15,7 @@
  {
   "doctype": "Item Tax Template",
   "title": "_Test Account Excise Duty @ 12",
+  "company": "_Test Company",
   "taxes": [
    {
     "doctype": "Item Tax Template Detail",
@@ -26,6 +28,7 @@
  {
   "doctype": "Item Tax Template",
   "title": "_Test Account Excise Duty @ 15",
+  "company": "_Test Company",
   "taxes": [
    {
     "doctype": "Item Tax Template Detail",
@@ -38,6 +41,7 @@
  {
   "doctype": "Item Tax Template",
   "title": "_Test Account Excise Duty @ 20",
+  "company": "_Test Company",
   "taxes": [
    {
     "doctype": "Item Tax Template Detail",
@@ -50,6 +54,7 @@
  {
   "doctype": "Item Tax Template",
   "title": "_Test Item Tax Template 1",
+  "company": "_Test Company",
   "taxes": [
    {
     "doctype": "Item Tax Template Detail",
diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.js b/erpnext/accounts/doctype/journal_entry/journal_entry.js
index 5685f83..a09face 100644
--- a/erpnext/accounts/doctype/journal_entry/journal_entry.js
+++ b/erpnext/accounts/doctype/journal_entry/journal_entry.js
@@ -13,15 +13,16 @@
 	refresh: function(frm) {
 		erpnext.toggle_naming_series();
 
-		if(frm.doc.docstatus==1) {
+		if(frm.doc.docstatus > 0) {
 			frm.add_custom_button(__('Ledger'), function() {
 				frappe.route_options = {
 					"voucher_no": frm.doc.name,
 					"from_date": frm.doc.posting_date,
-					"to_date": frm.doc.posting_date,
+					"to_date": moment(frm.doc.modified).format('YYYY-MM-DD'),
 					"company": frm.doc.company,
 					"finance_book": frm.doc.finance_book,
-					"group_by_voucher": 0
+					"group_by": '',
+					"show_cancelled_entries": frm.doc.docstatus === 2
 				};
 				frappe.set_route("query-report", "General Ledger");
 			}, __('View'));
diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.json b/erpnext/accounts/doctype/journal_entry/journal_entry.json
index af2aa65..4573c50 100644
--- a/erpnext/accounts/doctype/journal_entry/journal_entry.json
+++ b/erpnext/accounts/doctype/journal_entry/journal_entry.json
@@ -83,7 +83,7 @@
    "label": "Entry Type",
    "oldfieldname": "voucher_type",
    "oldfieldtype": "Select",
-   "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",
+   "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\nDeferred Revenue\nDeferred Expense",
    "reqd": 1,
    "search_index": 1
   },
diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py
index caaf30f..cfdae93 100644
--- a/erpnext/accounts/doctype/journal_entry/journal_entry.py
+++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py
@@ -10,6 +10,7 @@
 from erpnext.accounts.party import get_party_account
 from erpnext.hr.doctype.expense_claim.expense_claim import update_reimbursed_amount
 from erpnext.accounts.doctype.invoice_discounting.invoice_discounting import get_party_account_based_on_invoice_discounting
+from erpnext.accounts.deferred_revenue import get_deferred_booking_accounts
 
 from six import string_types, iteritems
 
@@ -265,7 +266,10 @@
 				# set totals
 				if not d.reference_name in self.reference_totals:
 					self.reference_totals[d.reference_name] = 0.0
-				self.reference_totals[d.reference_name] += flt(d.get(dr_or_cr))
+
+				if self.voucher_type not in ('Deferred Revenue', 'Deferred Expense'):
+					self.reference_totals[d.reference_name] += flt(d.get(dr_or_cr))
+
 				self.reference_types[d.reference_name] = d.reference_type
 				self.reference_accounts[d.reference_name] = d.account
 
@@ -277,10 +281,16 @@
 
 				# check if party and account match
 				if d.reference_type in ("Sales Invoice", "Purchase Invoice"):
-					if d.reference_type == "Sales Invoice":
-						party_account = get_party_account_based_on_invoice_discounting(d.reference_name) or against_voucher[1]
+					if self.voucher_type in ('Deferred Revenue', 'Deferred Expense') and d.reference_detail_no:
+						debit_or_credit = 'Debit' if d.debit else 'Credit'
+						party_account = get_deferred_booking_accounts(d.reference_type, d.reference_detail_no,
+							debit_or_credit)
 					else:
-						party_account = against_voucher[1]
+						if d.reference_type == "Sales Invoice":
+							party_account = get_party_account_based_on_invoice_discounting(d.reference_name) or against_voucher[1]
+						else:
+							party_account = against_voucher[1]
+
 					if (against_voucher[0] != d.party or party_account != d.account):
 						frappe.throw(_("Row {0}: Party / Account does not match with {1} / {2} in {3} {4}")
 							.format(d.idx, field_dict.get(d.reference_type)[0], field_dict.get(d.reference_type)[1],
@@ -513,14 +523,20 @@
 						"against_voucher_type": d.reference_type,
 						"against_voucher": d.reference_name,
 						"remarks": remarks,
+						"voucher_detail_no": d.reference_detail_no,
 						"cost_center": d.cost_center,
 						"project": d.project,
 						"finance_book": self.finance_book
 					}, item=d)
 				)
 
+		if self.voucher_type in ('Deferred Revenue', 'Deferred Expense'):
+			update_outstanding = 'No'
+		else:
+			update_outstanding = 'Yes'
+
 		if gl_map:
-			make_gl_entries(gl_map, cancel=cancel, adv_adj=adv_adj)
+			make_gl_entries(gl_map, cancel=cancel, adv_adj=adv_adj, update_outstanding=update_outstanding)
 
 	def get_balance(self):
 		if not self.get('accounts'):
@@ -824,6 +840,7 @@
 	return [{"account": a, "balance": get_balance_on(a)} for a in accounts]
 
 
+@frappe.whitelist()
 def get_against_jv(doctype, txt, searchfield, start, page_len, filters):
 	return frappe.db.sql("""select jv.name, jv.posting_date, jv.user_remark
 		from `tabJournal Entry` jv, `tabJournal Entry Account` jv_detail
diff --git a/erpnext/accounts/doctype/journal_entry/test_journal_entry.py b/erpnext/accounts/doctype/journal_entry/test_journal_entry.py
index 6996c77..23ad1ee 100644
--- a/erpnext/accounts/doctype/journal_entry/test_journal_entry.py
+++ b/erpnext/accounts/doctype/journal_entry/test_journal_entry.py
@@ -204,11 +204,8 @@
 		self.assertEqual(jv.inter_company_journal_entry_reference, "")
 		self.assertEqual(jv1.inter_company_journal_entry_reference, "")
 
-	def test_jv_for_enable_allow_cost_center_in_entry_of_bs_account(self):
+	def test_jv_with_cost_centre(self):
 		from erpnext.accounts.doctype.cost_center.test_cost_center import create_cost_center
-		accounts_settings = frappe.get_doc('Accounts Settings', 'Accounts Settings')
-		accounts_settings.allow_cost_center_in_entry_of_bs_account = 1
-		accounts_settings.save()
 		cost_center = "_Test Cost Center for BS Account - _TC"
 		create_cost_center(cost_center_name="_Test Cost Center for BS Account", company="_Test Company")
 		jv = make_journal_entry("_Test Cash - _TC", "_Test Bank - _TC", 100, cost_center = cost_center, save=False)
@@ -237,15 +234,45 @@
 		for gle in gl_entries:
 			self.assertEqual(expected_values[gle.account]["cost_center"], gle.cost_center)
 
-		accounts_settings.allow_cost_center_in_entry_of_bs_account = 0
-		accounts_settings.save()
+	def test_jv_with_project(self):
+		from erpnext.projects.doctype.project.test_project import make_project
+		project = make_project({
+			'project_name': 'Journal Entry Project',
+			'project_template_name': 'Test Project Template',
+			'start_date': '2020-01-01'
+		})
 
-	def test_jv_account_and_party_balance_for_enable_allow_cost_center_in_entry_of_bs_account(self):
+		jv = make_journal_entry("_Test Cash - _TC", "_Test Bank - _TC", 100, save=False)
+		for d in jv.accounts:
+			d.project = project.project_name
+		jv.voucher_type = "Bank Entry"
+		jv.multi_currency = 0
+		jv.cheque_no = "112233"
+		jv.cheque_date = nowdate()
+		jv.insert()
+		jv.submit()
+
+		expected_values = {
+			"_Test Cash - _TC": {
+				"project": project.project_name
+			},
+			"_Test Bank - _TC": {
+				"project": project.project_name
+			}
+		}
+
+		gl_entries = frappe.db.sql("""select account, project, debit, credit
+			from `tabGL Entry` where voucher_type='Journal Entry' and voucher_no=%s
+			order by account asc""", jv.name, as_dict=1)
+
+		self.assertTrue(gl_entries)
+
+		for gle in gl_entries:
+			self.assertEqual(expected_values[gle.account]["project"], gle.project)
+
+	def test_jv_account_and_party_balance_with_cost_centre(self):
 		from erpnext.accounts.doctype.cost_center.test_cost_center import create_cost_center
 		from erpnext.accounts.utils import get_balance_on
-		accounts_settings = frappe.get_doc('Accounts Settings', 'Accounts Settings')
-		accounts_settings.allow_cost_center_in_entry_of_bs_account = 1
-		accounts_settings.save()
 		cost_center = "_Test Cost Center for BS Account - _TC"
 		create_cost_center(cost_center_name="_Test Cost Center for BS Account", company="_Test Company")
 		jv = make_journal_entry("_Test Cash - _TC", "_Test Bank - _TC", 100, cost_center = cost_center, save=False)
@@ -261,9 +288,6 @@
 		account_balance = get_balance_on(account="_Test Bank - _TC", cost_center=cost_center)
 		self.assertEqual(expected_account_balance, account_balance)
 
-		accounts_settings.allow_cost_center_in_entry_of_bs_account = 0
-		accounts_settings.save()
-
 def make_journal_entry(account1, account2, amount, cost_center=None, posting_date=None, exchange_rate=1, save=True, submit=False, project=None):
 	if not cost_center:
 		cost_center = "_Test Cost Center - _TC"
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 ff3533a..774159d 100644
--- a/erpnext/accounts/doctype/journal_entry_account/journal_entry_account.json
+++ b/erpnext/accounts/doctype/journal_entry_account/journal_entry_account.json
@@ -33,6 +33,7 @@
   "reference_type",
   "reference_name",
   "reference_due_date",
+  "reference_detail_no",
   "col_break3",
   "is_advance",
   "user_remark",
@@ -268,12 +269,18 @@
    "fieldtype": "Link",
    "label": "Bank Account",
    "options": "Bank Account"
+  },
+  {
+   "fieldname": "reference_detail_no",
+   "fieldtype": "Data",
+   "hidden": 1,
+   "label": "Reference Detail No"
   }
  ],
  "idx": 1,
  "istable": 1,
  "links": [],
- "modified": "2020-06-18 14:06:54.833738",
+ "modified": "2020-06-24 14:06:54.833738",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "Journal Entry Account",
diff --git a/erpnext/accounts/doctype/loyalty_point_entry/loyalty_point_entry.json b/erpnext/accounts/doctype/loyalty_point_entry/loyalty_point_entry.json
index 5975198..4c1be65 100644
--- a/erpnext/accounts/doctype/loyalty_point_entry/loyalty_point_entry.json
+++ b/erpnext/accounts/doctype/loyalty_point_entry/loyalty_point_entry.json
@@ -1,426 +1,123 @@
 {
- "allow_copy": 0, 
- "allow_guest_to_view": 0, 
- "allow_import": 0, 
- "allow_rename": 0, 
- "autoname": "", 
- "beta": 0, 
- "creation": "2018-01-23 05:40:18.117583", 
- "custom": 0, 
- "docstatus": 0, 
- "doctype": "DocType", 
- "document_type": "", 
- "editable_grid": 1, 
- "engine": "InnoDB", 
+ "creation": "2018-01-23 05:40:18.117583",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "loyalty_program",
+  "loyalty_program_tier",
+  "customer",
+  "invoice_type",
+  "invoice",
+  "redeem_against",
+  "loyalty_points",
+  "purchase_amount",
+  "expiry_date",
+  "posting_date",
+  "company"
+ ],
  "fields": [
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "loyalty_program", 
-   "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": "Loyalty Program", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Loyalty Program", 
-   "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": "loyalty_program",
+   "fieldtype": "Link",
+   "label": "Loyalty Program",
+   "options": "Loyalty Program"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "loyalty_program_tier", 
-   "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": "Loyalty Program Tier", 
-   "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": "loyalty_program_tier",
+   "fieldtype": "Data",
+   "label": "Loyalty Program Tier"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "customer", 
-   "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": "Customer", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Customer", 
-   "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": "customer",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "label": "Customer",
+   "options": "Customer"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "sales_invoice", 
-   "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": "Sales Invoice", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Sales Invoice", 
-   "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": "redeem_against",
+   "fieldtype": "Link",
+   "label": "Redeem Against",
+   "options": "Loyalty Point Entry"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "redeem_against", 
-   "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": "Redeem Against", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Loyalty Point Entry", 
-   "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": "loyalty_points",
+   "fieldtype": "Int",
+   "in_list_view": 1,
+   "label": "Loyalty Points"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "loyalty_points", 
-   "fieldtype": "Int", 
-   "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": "Loyalty Points", 
-   "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": "purchase_amount",
+   "fieldtype": "Currency",
+   "label": "Purchase Amount"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "purchase_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": "Purchase 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": "expiry_date",
+   "fieldtype": "Date",
+   "in_list_view": 1,
+   "label": "Expiry Date"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "expiry_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": "Expiry 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": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "posting_date",
+   "fieldtype": "Date",
+   "label": "Posting Date"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "posting_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": "Posting 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": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "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, 
-   "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
+   "fieldname": "invoice_type",
+   "fieldtype": "Link",
+   "label": "Invoice Type",
+   "options": "DocType"
+  },
+  {
+   "fieldname": "invoice",
+   "fieldtype": "Dynamic Link",
+   "in_list_view": 1,
+   "label": "Invoice",
+   "options": "invoice_type"
   }
- ], 
- "has_web_view": 0, 
- "hide_heading": 0, 
- "hide_toolbar": 0, 
- "idx": 0, 
- "image_view": 0, 
- "in_create": 1, 
- "is_submittable": 0, 
- "issingle": 0, 
- "istable": 0, 
- "max_attachments": 0, 
- "modified": "2018-08-29 16:05:22.810347", 
- "modified_by": "Administrator", 
- "module": "Accounts", 
- "name": "Loyalty Point Entry", 
- "name_case": "", 
- "owner": "Administrator", 
+ ],
+ "in_create": 1,
+ "modified": "2020-01-30 17:27:55.964242",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "Loyalty Point Entry",
+ "owner": "Administrator",
  "permissions": [
   {
-   "amend": 0, 
-   "cancel": 0, 
-   "create": 0, 
-   "delete": 0, 
-   "email": 1, 
-   "export": 1, 
-   "if_owner": 0, 
-   "import": 0, 
-   "permlevel": 0, 
-   "print": 1, 
-   "read": 1, 
-   "report": 1, 
-   "role": "Auditor", 
-   "set_user_permissions": 0, 
-   "share": 0, 
-   "submit": 0, 
-   "write": 0
-  }, 
+   "email": 1,
+   "export": 1,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "Auditor"
+  },
   {
-   "amend": 0, 
-   "cancel": 0, 
-   "create": 0, 
-   "delete": 0, 
-   "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": 0, 
-   "submit": 0, 
-   "write": 0
-  }, 
+   "email": 1,
+   "export": 1,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "Accounts Manager"
+  },
   {
-   "amend": 0, 
-   "cancel": 0, 
-   "create": 0, 
-   "delete": 0, 
-   "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": 0, 
-   "submit": 0, 
-   "write": 0
+   "email": 1,
+   "export": 1,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "Accounts User"
   }
- ], 
- "quick_entry": 1, 
- "read_only": 0, 
- "read_only_onload": 0, 
- "show_name_in_global_search": 0, 
- "sort_field": "modified", 
- "sort_order": "DESC", 
- "title_field": "customer", 
- "track_changes": 1, 
- "track_seen": 0
+ ],
+ "quick_entry": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "title_field": "customer",
+ "track_changes": 1
 }
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/loyalty_point_entry/loyalty_point_entry.py b/erpnext/accounts/doctype/loyalty_point_entry/loyalty_point_entry.py
index d65a7d8..3579a1a 100644
--- a/erpnext/accounts/doctype/loyalty_point_entry/loyalty_point_entry.py
+++ b/erpnext/accounts/doctype/loyalty_point_entry/loyalty_point_entry.py
@@ -18,7 +18,7 @@
 		date = today()
 
 	return frappe.db.sql('''
-		select name, loyalty_points, expiry_date, loyalty_program_tier, sales_invoice
+		select name, loyalty_points, expiry_date, loyalty_program_tier, invoice_type, invoice
 		from `tabLoyalty Point Entry`
 		where customer=%s and loyalty_program=%s
 			and expiry_date>=%s and loyalty_points>0 and company=%s
diff --git a/erpnext/accounts/doctype/loyalty_program/loyalty_program.py b/erpnext/accounts/doctype/loyalty_program/loyalty_program.py
index 563165b..cb753a3 100644
--- a/erpnext/accounts/doctype/loyalty_program/loyalty_program.py
+++ b/erpnext/accounts/doctype/loyalty_program/loyalty_program.py
@@ -36,7 +36,8 @@
 		return {"loyalty_points": 0, "total_spent": 0}
 
 @frappe.whitelist()
-def get_loyalty_program_details_with_points(customer, loyalty_program=None, expiry_date=None, company=None, silent=False, include_expired_entry=False, current_transaction_amount=0):
+def get_loyalty_program_details_with_points(customer, loyalty_program=None, expiry_date=None, company=None, \
+		silent=False, include_expired_entry=False, current_transaction_amount=0):
 	lp_details = get_loyalty_program_details(customer, loyalty_program, company=company, silent=silent)
 	loyalty_program = frappe.get_doc("Loyalty Program", loyalty_program)
 	lp_details.update(get_loyalty_details(customer, loyalty_program.name, expiry_date, company, include_expired_entry))
@@ -59,10 +60,10 @@
 	if not loyalty_program:
 		loyalty_program = frappe.db.get_value("Customer", customer, "loyalty_program")
 
-		if not (loyalty_program or silent):
+		if not loyalty_program and not silent:
 			frappe.throw(_("Customer isn't enrolled in any Loyalty Program"))
 		elif silent and not loyalty_program:
-			return frappe._dict({"loyalty_program": None})
+			return frappe._dict({"loyalty_programs": None})
 
 	if not company:
 		company = frappe.db.get_default("company") or frappe.get_all("Company")[0].name
diff --git a/erpnext/accounts/doctype/loyalty_program/test_loyalty_program.py b/erpnext/accounts/doctype/loyalty_program/test_loyalty_program.py
index 341884c..ee73cca 100644
--- a/erpnext/accounts/doctype/loyalty_program/test_loyalty_program.py
+++ b/erpnext/accounts/doctype/loyalty_program/test_loyalty_program.py
@@ -27,7 +27,7 @@
 		customer = frappe.get_doc('Customer', {"customer_name": "Test Loyalty Customer"})
 		earned_points = get_points_earned(si_original)
 
-		lpe = frappe.get_doc('Loyalty Point Entry', {'sales_invoice': si_original.name, 'customer': si_original.customer})
+		lpe = frappe.get_doc('Loyalty Point Entry', {'invoice_type': 'Sales Invoice', 'invoice': si_original.name, 'customer': si_original.customer})
 
 		self.assertEqual(si_original.get('loyalty_program'), customer.loyalty_program)
 		self.assertEqual(lpe.get('loyalty_program_tier'), customer.loyalty_program_tier)
@@ -42,8 +42,8 @@
 
 		earned_after_redemption = get_points_earned(si_redeem)
 
-		lpe_redeem = frappe.get_doc('Loyalty Point Entry', {'sales_invoice': si_redeem.name, 'redeem_against': lpe.name})
-		lpe_earn = frappe.get_doc('Loyalty Point Entry', {'sales_invoice': si_redeem.name, 'name': ['!=', lpe_redeem.name]})
+		lpe_redeem = frappe.get_doc('Loyalty Point Entry', {'invoice_type': 'Sales Invoice', 'invoice': si_redeem.name, 'redeem_against': lpe.name})
+		lpe_earn = frappe.get_doc('Loyalty Point Entry', {'invoice_type': 'Sales Invoice', 'invoice': si_redeem.name, 'name': ['!=', lpe_redeem.name]})
 
 		self.assertEqual(lpe_earn.loyalty_points, earned_after_redemption)
 		self.assertEqual(lpe_redeem.loyalty_points, (-1*earned_points))
@@ -66,7 +66,7 @@
 
 		earned_points = get_points_earned(si_original)
 
-		lpe = frappe.get_doc('Loyalty Point Entry', {'sales_invoice': si_original.name, 'customer': si_original.customer})
+		lpe = frappe.get_doc('Loyalty Point Entry', {'invoice_type': 'Sales Invoice', 'invoice': si_original.name, 'customer': si_original.customer})
 
 		self.assertEqual(si_original.get('loyalty_program'), customer.loyalty_program)
 		self.assertEqual(lpe.get('loyalty_program_tier'), customer.loyalty_program_tier)
@@ -82,8 +82,8 @@
 		customer = frappe.get_doc('Customer', {"customer_name": "Test Loyalty Customer"})
 		earned_after_redemption = get_points_earned(si_redeem)
 
-		lpe_redeem = frappe.get_doc('Loyalty Point Entry', {'sales_invoice': si_redeem.name, 'redeem_against': lpe.name})
-		lpe_earn = frappe.get_doc('Loyalty Point Entry', {'sales_invoice': si_redeem.name, 'name': ['!=', lpe_redeem.name]})
+		lpe_redeem = frappe.get_doc('Loyalty Point Entry', {'invoice_type': 'Sales Invoice', 'invoice': si_redeem.name, 'redeem_against': lpe.name})
+		lpe_earn = frappe.get_doc('Loyalty Point Entry', {'invoice_type': 'Sales Invoice', 'invoice': si_redeem.name, 'name': ['!=', lpe_redeem.name]})
 
 		self.assertEqual(lpe_earn.loyalty_points, earned_after_redemption)
 		self.assertEqual(lpe_redeem.loyalty_points, (-1*earned_points))
@@ -101,7 +101,7 @@
 		si.insert()
 		si.submit()
 
-		lpe = frappe.get_doc('Loyalty Point Entry', {'sales_invoice': si.name, 'customer': si.customer})
+		lpe = frappe.get_doc('Loyalty Point Entry', {'invoice_type': 'Sales Invoice', 'invoice': si.name, 'customer': si.customer})
 		self.assertEqual(True, not (lpe is None))
 
 		# cancelling sales invoice
@@ -118,7 +118,7 @@
 		si_original.submit()
 
 		earned_points = get_points_earned(si_original)
-		lpe_original = frappe.get_doc('Loyalty Point Entry', {'sales_invoice': si_original.name, 'customer': si_original.customer})
+		lpe_original = frappe.get_doc('Loyalty Point Entry', {'invoice_type': 'Sales Invoice', 'invoice': si_original.name, 'customer': si_original.customer})
 		self.assertEqual(lpe_original.loyalty_points, earned_points)
 
 		# create sales invoice return
@@ -130,10 +130,10 @@
 		si_return.submit()
 
 		# fetch original invoice again as its status would have been updated
-		si_original = frappe.get_doc('Sales Invoice', lpe_original.sales_invoice)
+		si_original = frappe.get_doc('Sales Invoice', lpe_original.invoice)
 
 		earned_points = get_points_earned(si_original)
-		lpe_after_return = frappe.get_doc('Loyalty Point Entry', {'sales_invoice': si_original.name, 'customer': si_original.customer})
+		lpe_after_return = frappe.get_doc('Loyalty Point Entry', {'invoice_type': 'Sales Invoice', 'invoice': si_original.name, 'customer': si_original.customer})
 		self.assertEqual(lpe_after_return.loyalty_points, earned_points)
 		self.assertEqual(True, (lpe_original.loyalty_points > lpe_after_return.loyalty_points))
 
diff --git a/erpnext/accounts/doctype/opening_invoice_creation_tool/opening_invoice_creation_tool.py b/erpnext/accounts/doctype/opening_invoice_creation_tool/opening_invoice_creation_tool.py
index 54464e7..a53417e 100644
--- a/erpnext/accounts/doctype/opening_invoice_creation_tool/opening_invoice_creation_tool.py
+++ b/erpnext/accounts/doctype/opening_invoice_creation_tool/opening_invoice_creation_tool.py
@@ -68,6 +68,9 @@
 		if not self.company:
 			frappe.throw(_("Please select the Company"))
 
+		company_details = frappe.get_cached_value('Company', self.company,
+			["default_currency", "default_letter_head"], as_dict=1) or {}
+
 		for row in self.invoices:
 			if not row.qty:
 				row.qty = 1.0
@@ -99,6 +102,12 @@
 			if not args:
 				continue
 
+			if company_details:
+				args.update({
+					"currency": company_details.get("default_currency"),
+					"letter_head": company_details.get("default_letter_head")
+				})
+
 			doc = frappe.get_doc(args).insert()
 			doc.submit()
 			names.append(doc.name)
@@ -172,8 +181,7 @@
 			"due_date": row.due_date,
 			"posting_date": row.posting_date,
 			frappe.scrub(party_type): row.party,
-			"doctype": "Sales Invoice" if self.invoice_type == "Sales" else "Purchase Invoice",
-			"currency": frappe.get_cached_value('Company',  self.company,  "default_currency")
+			"doctype": "Sales Invoice" if self.invoice_type == "Sales" else "Purchase Invoice"
 		})
 
 		accounting_dimension = get_accounting_dimensions()
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.js b/erpnext/accounts/doctype/payment_entry/payment_entry.js
index a47da78..adfaade 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.js
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.js
@@ -90,7 +90,7 @@
 
 		frm.set_query("reference_doctype", "references", function() {
 			if (frm.doc.party_type=="Customer") {
-				var doctypes = ["Sales Order", "Sales Invoice", "Journal Entry"];
+				var doctypes = ["Sales Order", "Sales Invoice", "Journal Entry", "Dunning"];
 			} else if (frm.doc.party_type=="Supplier") {
 				var doctypes = ["Purchase Order", "Purchase Invoice", "Journal Entry"];
 			} else if (frm.doc.party_type=="Employee") {
@@ -125,7 +125,7 @@
 			const child = locals[cdt][cdn];
 			const filters = {"docstatus": 1, "company": doc.company};
 			const party_type_doctypes = ['Sales Invoice', 'Sales Order', 'Purchase Invoice',
-				'Purchase Order', 'Expense Claim', 'Fees'];
+				'Purchase Order', 'Expense Claim', 'Fees', 'Dunning'];
 
 			if (in_list(party_type_doctypes, child.reference_doctype)) {
 				filters[doc.party_type.toLowerCase()] = doc.party;
@@ -172,8 +172,8 @@
 		frm.toggle_display("base_paid_amount", frm.doc.paid_from_account_currency != company_currency);
 
 		frm.toggle_display("base_received_amount", (
-			frm.doc.paid_to_account_currency != company_currency 
-			&& frm.doc.paid_from_account_currency != frm.doc.paid_to_account_currency 
+			frm.doc.paid_to_account_currency != company_currency
+			&& frm.doc.paid_from_account_currency != frm.doc.paid_to_account_currency
 			&& frm.doc.base_paid_amount != frm.doc.base_received_amount
 		));
 
@@ -234,14 +234,15 @@
 	},
 
 	show_general_ledger: 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,
 					"from_date": frm.doc.posting_date,
-					"to_date": frm.doc.posting_date,
+					"to_date": moment(frm.doc.modified).format('YYYY-MM-DD'),
 					"company": frm.doc.company,
-					group_by: ""
+					"group_by": "",
+					"show_cancelled_entries": frm.doc.docstatus === 2
 				};
 				frappe.set_route("query-report", "General Ledger");
 			}, "fa fa-table");
@@ -862,10 +863,10 @@
 			}
 
 			if(frm.doc.party_type=="Customer" &&
-				!in_list(["Sales Order", "Sales Invoice", "Journal Entry"], row.reference_doctype)
+				!in_list(["Sales Order", "Sales Invoice", "Journal Entry", "Dunning"], row.reference_doctype)
 			) {
 				frappe.model.set_value(row.doctype, row.name, "reference_doctype", null);
-				frappe.msgprint(__("Row #{0}: Reference Document Type must be one of Sales Order, Sales Invoice or Journal Entry", [row.idx]));
+				frappe.msgprint(__("Row #{0}: Reference Document Type must be one of Sales Order, Sales Invoice, Journal Entry or Dunning", [row.idx]));
 				return false;
 			}
 
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py
index 59611bc..f9db14b 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.py
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py
@@ -6,7 +6,7 @@
 import frappe, erpnext, json
 from frappe import _, scrub, ValidationError
 from frappe.utils import flt, comma_or, nowdate, getdate
-from erpnext.accounts.utils import get_outstanding_invoices, get_account_currency, get_balance_on, get_allow_cost_center_in_entry_of_bs_account
+from erpnext.accounts.utils import get_outstanding_invoices, get_account_currency, get_balance_on
 from erpnext.accounts.party import get_party_account
 from erpnext.accounts.doctype.journal_entry.journal_entry import get_default_bank_cash_account
 from erpnext.setup.utils import get_exchange_rate
@@ -199,8 +199,8 @@
 
 	def validate_account_type(self, account, account_types):
 		account_type = frappe.db.get_value("Account", account, "account_type")
-		if account_type not in account_types:
-			frappe.throw(_("Account Type for {0} must be {1}").format(account, comma_or(account_types)))
+		# if account_type not in account_types:
+		# 	frappe.throw(_("Account Type for {0} must be {1}").format(account, comma_or(account_types)))
 
 	def set_exchange_rate(self):
 		if self.paid_from and not self.source_exchange_rate:
@@ -223,7 +223,7 @@
 		if self.party_type == "Student":
 			valid_reference_doctypes = ("Fees")
 		elif self.party_type == "Customer":
-			valid_reference_doctypes = ("Sales Order", "Sales Invoice", "Journal Entry")
+			valid_reference_doctypes = ("Sales Order", "Sales Invoice", "Journal Entry", "Dunning")
 		elif self.party_type == "Supplier":
 			valid_reference_doctypes = ("Purchase Order", "Purchase Invoice", "Journal Entry")
 		elif self.party_type == "Employee":
@@ -658,7 +658,7 @@
 			.format(frappe.db.escape(args["voucher_type"]), frappe.db.escape(args["voucher_no"]))
 
 	# Add cost center condition
-	if args.get("cost_center") and get_allow_cost_center_in_entry_of_bs_account():
+	if args.get("cost_center"):
 		condition += " and cost_center='%s'" % args.get("cost_center")
 
 	date_fields_dict = {
@@ -897,6 +897,10 @@
 		total_amount = ref_doc.get("grand_total")
 		exchange_rate = 1
 		outstanding_amount = ref_doc.get("outstanding_amount")
+	if reference_doctype == "Dunning":
+		total_amount = ref_doc.get("dunning_amount")
+		exchange_rate = 1
+		outstanding_amount = ref_doc.get("dunning_amount")
 	elif reference_doctype == "Journal Entry" and ref_doc.docstatus == 1:
 		total_amount = ref_doc.get("total_amount")
 		if ref_doc.multi_currency:
@@ -951,7 +955,7 @@
 	if dt in ("Sales Order", "Purchase Order") and flt(doc.per_billed, 2) > 0:
 		frappe.throw(_("Can only make payment against unbilled {0}").format(dt))
 
-	if dt in ("Sales Invoice", "Sales Order"):
+	if dt in ("Sales Invoice", "Sales Order", "Dunning"):
 		party_type = "Customer"
 	elif dt in ("Purchase Invoice", "Purchase Order"):
 		party_type = "Supplier"
@@ -980,7 +984,7 @@
 		party_account_currency = doc.get("party_account_currency") or get_account_currency(party_account)
 
 	# payment type
-	if (dt == "Sales Order" or (dt in ("Sales Invoice", "Fees") and doc.outstanding_amount > 0)) \
+	if (dt == "Sales Order" or (dt in ("Sales Invoice", "Fees", "Dunning") and doc.outstanding_amount > 0)) \
 		or (dt=="Purchase Invoice" and doc.outstanding_amount < 0):
 			payment_type = "Receive"
 	else:
@@ -1006,6 +1010,9 @@
 	elif dt == "Fees":
 		grand_total = doc.grand_total
 		outstanding_amount = doc.outstanding_amount
+	elif dt == "Dunning":
+		grand_total = doc.grand_total
+		outstanding_amount = doc.grand_total
 	else:
 		if party_account_currency == doc.company_currency:
 			grand_total = flt(doc.get("base_rounded_total") or doc.base_grand_total)
@@ -1029,14 +1036,14 @@
 		if bank_amount:
 			received_amount = bank_amount
 		else:
-			received_amount = paid_amount * doc.conversion_rate
+			received_amount = paid_amount * doc.get('conversion_rate', 1)
 	else:
 		received_amount = abs(outstanding_amount)
 		if bank_amount:
 			paid_amount = bank_amount
 		else:
 			# if party account currency and bank currency is different then populate paid amount as well
-			paid_amount = received_amount * doc.conversion_rate
+			paid_amount = received_amount * doc.get('conversion_rate', 1)
 
 	pe = frappe.new_doc("Payment Entry")
 	pe.payment_type = payment_type
@@ -1075,15 +1082,35 @@
 			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
-			})
+			if dt == "Dunning":
+				pe.append("references", {
+					'reference_doctype': 'Sales Invoice',
+					'reference_name': doc.get('sales_invoice'),
+					"bill_no": doc.get("bill_no"),
+					"due_date": doc.get("due_date"),
+					'total_amount': doc.get('outstanding_amount'),
+					'outstanding_amount': doc.get('outstanding_amount'),
+					'allocated_amount': doc.get('outstanding_amount')
+				})
+				pe.append("references", {
+					'reference_doctype': dt,
+					'reference_name': dn,
+					"bill_no": doc.get("bill_no"),
+					"due_date": doc.get("due_date"),
+					'total_amount': doc.get('dunning_amount'),
+					'outstanding_amount': doc.get('dunning_amount'),
+					'allocated_amount': doc.get('dunning_amount')
+				})
+			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()
@@ -1172,4 +1199,4 @@
 
 	}, target_doc, set_missing_values)
 
-	return doclist
+	return doclist
\ 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 8bb741f..772fc1a 100644
--- a/erpnext/accounts/doctype/payment_entry/test_payment_entry.py
+++ b/erpnext/accounts/doctype/payment_entry/test_payment_entry.py
@@ -460,11 +460,8 @@
 		outstanding_amount = flt(frappe.db.get_value("Sales Invoice", si.name, "outstanding_amount"))
 		self.assertEqual(outstanding_amount, 0)
 
-	def test_payment_entry_against_sales_invoice_for_enable_allow_cost_center_in_entry_of_bs_account(self):
+	def test_payment_entry_against_sales_invoice_with_cost_centre(self):
 		from erpnext.accounts.doctype.cost_center.test_cost_center import create_cost_center
-		accounts_settings = frappe.get_doc('Accounts Settings', 'Accounts Settings')
-		accounts_settings.allow_cost_center_in_entry_of_bs_account = 1
-		accounts_settings.save()
 		cost_center = "_Test Cost Center for BS Account - _TC"
 		create_cost_center(cost_center_name="_Test Cost Center for BS Account", company="_Test Company")
 
@@ -499,39 +496,8 @@
 		for gle in gl_entries:
 			self.assertEqual(expected_values[gle.account]["cost_center"], gle.cost_center)
 
-		accounts_settings.allow_cost_center_in_entry_of_bs_account = 0
-		accounts_settings.save()
-
-	def test_payment_entry_against_sales_invoice_for_disable_allow_cost_center_in_entry_of_bs_account(self):
-		accounts_settings = frappe.get_doc('Accounts Settings', 'Accounts Settings')
-		accounts_settings.allow_cost_center_in_entry_of_bs_account = 0
-		accounts_settings.save()
-		si =  create_sales_invoice(debit_to="Debtors - _TC")
-
-		pe = get_payment_entry("Sales Invoice", si.name, bank_account="_Test Bank - _TC")
-
-		pe.reference_no = "112211-2"
-		pe.reference_date = nowdate()
-		pe.paid_to = "_Test Bank - _TC"
-		pe.paid_amount = si.grand_total
-		pe.insert()
-		pe.submit()
-
-		gl_entries = frappe.db.sql("""select account, cost_center, account_currency, debit, credit,
-			debit_in_account_currency, credit_in_account_currency
-			from `tabGL Entry` where voucher_type='Payment Entry' and voucher_no=%s
-			order by account asc""", pe.name, as_dict=1)
-
-		self.assertTrue(gl_entries)
-
-		for gle in gl_entries:
-			self.assertEqual(gle.cost_center, None)
-
-	def test_payment_entry_against_purchase_invoice_for_enable_allow_cost_center_in_entry_of_bs_account(self):
+	def test_payment_entry_against_purchase_invoice_with_cost_center(self):
 		from erpnext.accounts.doctype.cost_center.test_cost_center import create_cost_center
-		accounts_settings = frappe.get_doc('Accounts Settings', 'Accounts Settings')
-		accounts_settings.allow_cost_center_in_entry_of_bs_account = 1
-		accounts_settings.save()
 		cost_center = "_Test Cost Center for BS Account - _TC"
 		create_cost_center(cost_center_name="_Test Cost Center for BS Account", company="_Test Company")
 
@@ -566,40 +532,9 @@
 		for gle in gl_entries:
 			self.assertEqual(expected_values[gle.account]["cost_center"], gle.cost_center)
 
-		accounts_settings.allow_cost_center_in_entry_of_bs_account = 0
-		accounts_settings.save()
-
-	def test_payment_entry_against_purchase_invoice_for_disable_allow_cost_center_in_entry_of_bs_account(self):
-		accounts_settings = frappe.get_doc('Accounts Settings', 'Accounts Settings')
-		accounts_settings.allow_cost_center_in_entry_of_bs_account = 0
-		accounts_settings.save()
-		pi =  make_purchase_invoice(credit_to="Creditors - _TC")
-
-		pe = get_payment_entry("Purchase Invoice", pi.name, bank_account="_Test Bank - _TC")
-
-		pe.reference_no = "112222-2"
-		pe.reference_date = nowdate()
-		pe.paid_from = "_Test Bank - _TC"
-		pe.paid_amount = pi.grand_total
-		pe.insert()
-		pe.submit()
-
-		gl_entries = frappe.db.sql("""select account, cost_center, account_currency, debit, credit,
-			debit_in_account_currency, credit_in_account_currency
-			from `tabGL Entry` where voucher_type='Payment Entry' and voucher_no=%s
-			order by account asc""", pe.name, as_dict=1)
-
-		self.assertTrue(gl_entries)
-
-		for gle in gl_entries:
-			self.assertEqual(gle.cost_center, None)
-
-	def test_payment_entry_account_and_party_balance_for_enable_allow_cost_center_in_entry_of_bs_account(self):
+	def test_payment_entry_account_and_party_balance_with_cost_center(self):
 		from erpnext.accounts.doctype.cost_center.test_cost_center import create_cost_center
 		from erpnext.accounts.utils import get_balance_on
-		accounts_settings = frappe.get_doc('Accounts Settings', 'Accounts Settings')
-		accounts_settings.allow_cost_center_in_entry_of_bs_account = 1
-		accounts_settings.save()
 		cost_center = "_Test Cost Center for BS Account - _TC"
 		create_cost_center(cost_center_name="_Test Cost Center for BS Account", company="_Test Company")
 
@@ -630,9 +565,6 @@
 		self.assertEqual(expected_party_balance, party_balance)
 		self.assertEqual(expected_party_account_balance, party_account_balance)
 
-		accounts_settings.allow_cost_center_in_entry_of_bs_account = 0
-		accounts_settings.save()
-
 def create_payment_terms_template():
 
 	create_payment_term('Basic Amount Receivable')
@@ -665,4 +597,4 @@
 		frappe.get_doc({
 			'doctype': 'Payment Term',
 			'payment_term_name': name
-		}).insert()
\ No newline at end of file
+		}).insert()
diff --git a/erpnext/accounts/doctype/payment_order/payment_order.py b/erpnext/accounts/doctype/payment_order/payment_order.py
index 7ecdc41..4702e58 100644
--- a/erpnext/accounts/doctype/payment_order/payment_order.py
+++ b/erpnext/accounts/doctype/payment_order/payment_order.py
@@ -26,6 +26,7 @@
 		for d in self.references:
 			frappe.db.set_value(self.payment_order_type, d.get(frappe.scrub(self.payment_order_type)), ref_field, status)
 
+@frappe.whitelist()
 def get_mop_query(doctype, txt, searchfield, start, page_len, filters):
 	return frappe.db.sql(""" select mode_of_payment from `tabPayment Order Reference`
 		where parent = %(parent)s and mode_of_payment like %(txt)s
@@ -36,6 +37,7 @@
 			'txt': "%%%s%%" % txt
 		})
 
+@frappe.whitelist()
 def get_supplier_query(doctype, txt, searchfield, start, page_len, filters):
 	return frappe.db.sql(""" select supplier from `tabPayment Order Reference`
 		where parent = %(parent)s and supplier like %(txt)s and
@@ -86,4 +88,4 @@
 
 	je.flags.ignore_mandatory = True
 	je.save()
-	frappe.msgprint(_("{0} {1} created").format(je.doctype, je.name))
\ No newline at end of file
+	frappe.msgprint(_("{0} {1} created").format(je.doctype, je.name))
diff --git a/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.js b/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.js
index d3992d5..355fe96 100644
--- a/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.js
+++ b/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.js
@@ -73,6 +73,10 @@
 				};
 			}
 		});
+
+		this.frm.set_value('party_type', '');
+		this.frm.set_value('party', '');
+		this.frm.set_value('receivable_payable_account', '');
 	},
 
 	refresh: function() {
diff --git a/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py b/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py
index 3080496..2f8b634 100644
--- a/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py
+++ b/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py
@@ -48,7 +48,8 @@
 			select
 				"Journal Entry" as reference_type, t1.name as reference_name,
 				t1.posting_date, t1.remark as remarks, t2.name as reference_row,
-				{dr_or_cr} as amount, t2.is_advance
+				{dr_or_cr} as amount, t2.is_advance,
+				t2.account_currency as currency
 			from
 				`tabJournal Entry` t1, `tabJournal Entry Account` t2
 			where
@@ -88,7 +89,8 @@
 			if self.party_type == 'Customer' else "Purchase Invoice")
 
 		return frappe.db.sql(""" SELECT `tab{doc}`.name as reference_name, %(voucher_type)s as reference_type,
-				(sum(`tabGL Entry`.{dr_or_cr}) - sum(`tabGL Entry`.{reconciled_dr_or_cr})) as amount
+				(sum(`tabGL Entry`.{dr_or_cr}) - sum(`tabGL Entry`.{reconciled_dr_or_cr})) as amount,
+				account_currency as currency
 			FROM `tab{doc}`, `tabGL Entry`
 			WHERE
 				(`tab{doc}`.name = `tabGL Entry`.against_voucher or `tab{doc}`.name = `tabGL Entry`.voucher_no)
@@ -101,10 +103,10 @@
 			Having
 				amount > 0
 		""".format(
-			doc=voucher_type, 
-			dr_or_cr=dr_or_cr, 
-			reconciled_dr_or_cr=reconciled_dr_or_cr, 
-			party_type_field=frappe.scrub(self.party_type)), 
+			doc=voucher_type,
+			dr_or_cr=dr_or_cr,
+			reconciled_dr_or_cr=reconciled_dr_or_cr,
+			party_type_field=frappe.scrub(self.party_type)),
 			{
 				'party': self.party,
 				'party_type': self.party_type,
@@ -141,6 +143,7 @@
 			ent.invoice_number = e.get('voucher_no')
 			ent.invoice_date = e.get('posting_date')
 			ent.amount = flt(e.get('invoice_amount'))
+			ent.currency = e.get('currency')
 			ent.outstanding_amount = e.get('outstanding_amount')
 
 	def reconcile(self, args):
@@ -170,7 +173,7 @@
 			reconcile_against_document(lst)
 
 		if dr_or_cr_notes:
-			reconcile_dr_cr_note(dr_or_cr_notes)
+			reconcile_dr_cr_note(dr_or_cr_notes, self.company)
 
 		msgprint(_("Successfully Reconciled"))
 		self.get_unreconciled_entries()
@@ -261,7 +264,7 @@
 
 		return cond
 
-def reconcile_dr_cr_note(dr_cr_notes):
+def reconcile_dr_cr_note(dr_cr_notes, company):
 	for d in dr_cr_notes:
 		voucher_type = ('Credit Note'
 			if d.voucher_type == 'Sales Invoice' else 'Debit Note')
@@ -269,10 +272,14 @@
 		reconcile_dr_or_cr = ('debit_in_account_currency'
 			if d.dr_or_cr == 'credit_in_account_currency' else 'credit_in_account_currency')
 
+		company_currency = erpnext.get_company_currency(company)
+
 		jv = frappe.get_doc({
 			"doctype": "Journal Entry",
 			"voucher_type": voucher_type,
 			"posting_date": today(),
+			"company": company,
+			"multi_currency": 1 if d.currency != company_currency else 0,
 			"accounts": [
 				{
 					'account': d.account,
@@ -280,7 +287,8 @@
 					'party_type': d.party_type,
 					d.dr_or_cr: abs(d.allocated_amount),
 					'reference_type': d.against_voucher_type,
-					'reference_name': d.against_voucher
+					'reference_name': d.against_voucher,
+					'cost_center': erpnext.get_default_cost_center(company)
 				},
 				{
 					'account': d.account,
@@ -289,7 +297,8 @@
 					reconcile_dr_or_cr: (abs(d.allocated_amount)
 						if abs(d.unadjusted_amount) > abs(d.allocated_amount) else abs(d.unadjusted_amount)),
 					'reference_type': d.voucher_type,
-					'reference_name': d.voucher_no
+					'reference_name': d.voucher_no,
+					'cost_center': erpnext.get_default_cost_center(company)
 				}
 			]
 		})
diff --git a/erpnext/accounts/doctype/payment_reconciliation_invoice/payment_reconciliation_invoice.json b/erpnext/accounts/doctype/payment_reconciliation_invoice/payment_reconciliation_invoice.json
index ce7ce98..6a79a85 100644
--- a/erpnext/accounts/doctype/payment_reconciliation_invoice/payment_reconciliation_invoice.json
+++ b/erpnext/accounts/doctype/payment_reconciliation_invoice/payment_reconciliation_invoice.json
@@ -1,183 +1,80 @@
 {
- "allow_copy": 0, 
- "allow_import": 0, 
- "allow_rename": 0, 
- "beta": 0, 
- "creation": "2014-07-09 16:14:23.672922", 
- "custom": 0, 
- "docstatus": 0, 
- "doctype": "DocType", 
- "document_type": "", 
- "editable_grid": 1, 
+ "actions": [],
+ "creation": "2014-07-09 16:14:23.672922",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "invoice_type",
+  "invoice_number",
+  "invoice_date",
+  "col_break1",
+  "amount",
+  "outstanding_amount",
+  "currency"
+ ],
  "fields": [
   {
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "fieldname": "invoice_type", 
-   "fieldtype": "Select", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_list_view": 1, 
-   "label": "Invoice Type", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Sales Invoice\nPurchase Invoice\nJournal Entry", 
-   "permlevel": 0, 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 1, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "invoice_type",
+   "fieldtype": "Select",
+   "in_list_view": 1,
+   "label": "Invoice Type",
+   "options": "Sales Invoice\nPurchase Invoice\nJournal Entry",
+   "read_only": 1
+  },
   {
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "fieldname": "invoice_number", 
-   "fieldtype": "Dynamic Link", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_list_view": 1, 
-   "label": "Invoice Number", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "invoice_type", 
-   "permlevel": 0, 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 1, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "invoice_number",
+   "fieldtype": "Dynamic Link",
+   "in_list_view": 1,
+   "label": "Invoice Number",
+   "options": "invoice_type",
+   "read_only": 1
+  },
   {
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "fieldname": "invoice_date", 
-   "fieldtype": "Date", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_list_view": 1, 
-   "label": "Invoice Date", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 1, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "invoice_date",
+   "fieldtype": "Date",
+   "in_list_view": 1,
+   "label": "Invoice Date",
+   "read_only": 1
+  },
   {
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "fieldname": "col_break1", 
-   "fieldtype": "Column Break", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_list_view": 0, 
-   "label": "", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "col_break1",
+   "fieldtype": "Column Break"
+  },
   {
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "fieldname": "amount", 
-   "fieldtype": "Currency", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_list_view": 1, 
-   "label": "Amount", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 1, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "amount",
+   "fieldtype": "Currency",
+   "in_list_view": 1,
+   "label": "Amount",
+   "options": "currency",
+   "read_only": 1
+  },
   {
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "fieldname": "outstanding_amount", 
-   "fieldtype": "Currency", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_list_view": 1, 
-   "label": "Outstanding Amount", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 1, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "unique": 0
+   "fieldname": "outstanding_amount",
+   "fieldtype": "Currency",
+   "in_list_view": 1,
+   "label": "Outstanding Amount",
+   "options": "currency",
+   "read_only": 1
+  },
+  {
+   "fieldname": "currency",
+   "fieldtype": "Link",
+   "hidden": 1,
+   "label": "Currency",
+   "options": "Currency"
   }
- ], 
- "hide_heading": 0, 
- "hide_toolbar": 0, 
- "idx": 0, 
- "image_view": 0, 
- "in_create": 0, 
-
- "is_submittable": 0, 
- "issingle": 0, 
- "istable": 1, 
- "max_attachments": 0, 
- "modified": "2016-07-11 03:28:03.588476", 
- "modified_by": "Administrator", 
- "module": "Accounts", 
- "name": "Payment Reconciliation Invoice", 
- "name_case": "", 
- "owner": "Administrator", 
- "permissions": [], 
- "quick_entry": 1, 
- "read_only": 0, 
- "read_only_onload": 0, 
- "sort_field": "modified", 
- "sort_order": "DESC", 
- "track_seen": 0
+ ],
+ "istable": 1,
+ "links": [],
+ "modified": "2020-07-19 18:12:27.964073",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "Payment Reconciliation Invoice",
+ "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_reconciliation_payment/payment_reconciliation_payment.json b/erpnext/accounts/doctype/payment_reconciliation_payment/payment_reconciliation_payment.json
index 018bfd0..925a6f1 100644
--- a/erpnext/accounts/doctype/payment_reconciliation_payment/payment_reconciliation_payment.json
+++ b/erpnext/accounts/doctype/payment_reconciliation_payment/payment_reconciliation_payment.json
@@ -1,7 +1,9 @@
 {
+ "actions": [],
  "creation": "2014-07-09 16:13:35.452759",
  "doctype": "DocType",
  "editable_grid": 1,
+ "engine": "InnoDB",
  "field_order": [
   "reference_type",
   "reference_name",
@@ -16,7 +18,8 @@
   "difference_account",
   "difference_amount",
   "sec_break1",
-  "remark"
+  "remark",
+  "currency"
  ],
  "fields": [
   {
@@ -73,6 +76,7 @@
    "fieldtype": "Currency",
    "in_list_view": 1,
    "label": "Amount",
+   "options": "currency",
    "read_only": 1
   },
   {
@@ -81,6 +85,7 @@
    "fieldtype": "Currency",
    "in_list_view": 1,
    "label": "Allocated amount",
+   "options": "currency",
    "reqd": 1
   },
   {
@@ -106,16 +111,25 @@
    "fieldname": "difference_amount",
    "fieldtype": "Currency",
    "label": "Difference Amount",
+   "options": "currency",
    "print_hide": 1,
    "read_only": 1
   },
   {
    "fieldname": "section_break_10",
    "fieldtype": "Section Break"
+  },
+  {
+   "fieldname": "currency",
+   "fieldtype": "Link",
+   "hidden": 1,
+   "label": "Currency",
+   "options": "Currency"
   }
  ],
  "istable": 1,
- "modified": "2019-06-24 00:08:11.150796",
+ "links": [],
+ "modified": "2020-07-19 18:12:41.682347",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "Payment Reconciliation Payment",
diff --git a/erpnext/accounts/doctype/payment_request/payment_request.json b/erpnext/accounts/doctype/payment_request/payment_request.json
index eef6be1..8eadfd0 100644
--- a/erpnext/accounts/doctype/payment_request/payment_request.json
+++ b/erpnext/accounts/doctype/payment_request/payment_request.json
@@ -211,7 +211,7 @@
    "label": "IBAN"
   },
   {
-   "fetch_from": "bank.branch_code",
+   "fetch_from": "bank_account.branch_code",
    "fetch_if_empty": 1,
    "fieldname": "branch_code",
    "fieldtype": "Read Only",
@@ -352,7 +352,7 @@
  "in_create": 1,
  "is_submittable": 1,
  "links": [],
- "modified": "2020-05-29 17:38:49.392713",
+ "modified": "2020-07-17 14:06:42.185763",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "Payment Request",
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 87e02fe..e923d4e 100644
--- a/erpnext/accounts/doctype/period_closing_voucher/period_closing_voucher.js
+++ b/erpnext/accounts/doctype/period_closing_voucher/period_closing_voucher.js
@@ -25,9 +25,10 @@
 				frappe.route_options = {
 					"voucher_no": frm.doc.name,
 					"from_date": frm.doc.posting_date,
-					"to_date": frm.doc.posting_date,
+					"to_date": moment(frm.doc.modified).format('YYYY-MM-DD'),
 					"company": frm.doc.company,
-					group_by_voucher: 0
+					"group_by": "",
+					"show_cancelled_entries": frm.doc.docstatus === 2
 				};
 				frappe.set_route("query-report", "General Ledger");
 			}, "fa fa-table");
diff --git a/erpnext/accounts/page/pos/__init__.py b/erpnext/accounts/doctype/pos_closing_entry/__init__.py
similarity index 100%
copy from erpnext/accounts/page/pos/__init__.py
copy to erpnext/accounts/doctype/pos_closing_entry/__init__.py
diff --git a/erpnext/selling/doctype/pos_closing_voucher/closing_voucher_details.html b/erpnext/accounts/doctype/pos_closing_entry/closing_voucher_details.html
similarity index 71%
rename from erpnext/selling/doctype/pos_closing_voucher/closing_voucher_details.html
rename to erpnext/accounts/doctype/pos_closing_entry/closing_voucher_details.html
index 2412b07..983f495 100644
--- a/erpnext/selling/doctype/pos_closing_voucher/closing_voucher_details.html
+++ b/erpnext/accounts/doctype/pos_closing_entry/closing_voucher_details.html
@@ -12,15 +12,15 @@
 								</thead>
 								<tbody>
 									<tr>
-										<td class="text-left">{{ _('Grand Total') }}</td>
-										<td class='text-right'>{{ data.grand_total or '' }} {{ currency.symbol }}</td>
+										<td class="text-left font-bold">{{ _('Grand Total') }}</td>
+										<td class='text-right'> {{ frappe.utils.fmt_money(data.grand_total or '', currency=currency) }}</td>
 									</tr>
 									<tr>
-										<td class="text-left">{{ _('Net Total') }}</td>
-										<td class='text-right'>{{ data.net_total or '' }} {{ currency.symbol }}</td>
+										<td class="text-left font-bold">{{ _('Net Total') }}</td>
+										<td class='text-right'> {{ frappe.utils.fmt_money(data.net_total or '', currency=currency) }}</td>
 									</tr>
 									<tr>
-										<td class="text-left">{{ _('Total Quantity') }}</td>
+										<td class="text-left font-bold">{{ _('Total Quantity') }}</td>
 										<td class='text-right'>{{ data.total_quantity or '' }}</td>
 									</tr>
 
@@ -45,7 +45,7 @@
 								{% for d in data.payment_reconciliation %}
 									<tr>
 										<td class="text-left">{{ d.mode_of_payment }}</td>
-										<td class='text-right'>{{ d.expected_amount }} {{ currency.symbol }}</td>
+										<td class='text-right'> {{ frappe.utils.fmt_money(d.expected_amount - d.opening_amount, currency=currency) }}</td>
 									</tr>
 								{% endfor %}
 							</tbody>
@@ -55,12 +55,14 @@
 				<!-- Section end -->
 
 				<!-- Taxes section -->
+				{% if data.taxes %}
 				<div>
 						<h6 class="text-center uppercase" style="color: #8D99A6">{{ _("Taxes") }}</h6>
 						<div class="tax-break-up" style="overflow-x: auto;">
 							<table class="table table-bordered table-hover">
 								<thead>
 									<tr>
+										<th class="text-left">{{ _("Account") }}</th>
 										<th class="text-left">{{ _("Rate") }}</th>
 										<th class="text-right">{{ _("Amount") }}</th>
 									</tr>
@@ -68,14 +70,16 @@
 								<tbody>
 								{% for d in data.taxes %}
 									<tr>
+										<td class="text-left">{{ d.account_head }}</td>
 										<td class="text-left">{{ d.rate }} %</td>
-										<td class='text-right'>{{ d.amount }} {{ currency.symbol }}</td>
+										<td class='text-right'> {{ frappe.utils.fmt_money(d.amount, currency=currency) }}</td>
 									</tr>
 								{% endfor %}
 							</tbody>
 						</table>
 					</div>
 				</div>
+				{% endif %}
 				<!-- Section end -->
 
 			</div>
diff --git a/erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry.js b/erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry.js
new file mode 100644
index 0000000..8dcd2e4
--- /dev/null
+++ b/erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry.js
@@ -0,0 +1,149 @@
+// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+frappe.ui.form.on('POS Closing Entry', {
+	onload: function(frm) {
+		frm.set_query("pos_profile", function(doc) {
+			return {
+				filters: { 'user': doc.user }
+			};
+		});
+
+		frm.set_query("user", function(doc) {
+			return {
+				query: "erpnext.accounts.doctype.pos_closing_entry.pos_closing_entry.get_cashiers",
+				filters: { 'parent': doc.pos_profile }
+			};
+		});
+
+		frm.set_query("pos_opening_entry", function(doc) {
+			return { filters: { 'status': 'Open', 'docstatus': 1 } };
+		});
+		
+		if (frm.doc.docstatus === 0) frm.set_value("period_end_date", frappe.datetime.now_datetime());
+		if (frm.doc.docstatus === 1) set_html_data(frm);
+	},
+
+	pos_opening_entry(frm) {
+		if (frm.doc.pos_opening_entry && frm.doc.period_start_date && frm.doc.period_end_date && frm.doc.user) {
+			reset_values(frm);
+			frm.trigger("set_opening_amounts");
+			frm.trigger("get_pos_invoices");
+		}
+	},
+
+	set_opening_amounts(frm) {
+		frappe.db.get_doc("POS Opening Entry", frm.doc.pos_opening_entry)
+			.then(({ balance_details }) => {
+				balance_details.forEach(detail => {
+					frm.add_child("payment_reconciliation", {
+						mode_of_payment: detail.mode_of_payment,
+						opening_amount: detail.opening_amount,
+						expected_amount: detail.opening_amount
+					});
+				})
+			});
+	},
+
+	get_pos_invoices(frm) {
+		frappe.call({
+			method: 'erpnext.accounts.doctype.pos_closing_entry.pos_closing_entry.get_pos_invoices',
+			args: {
+				start: frappe.datetime.get_datetime_as_string(frm.doc.period_start_date),
+				end: frappe.datetime.get_datetime_as_string(frm.doc.period_end_date),
+				user: frm.doc.user
+			},
+			callback: (r) => {
+				let pos_docs = r.message;
+				set_form_data(pos_docs, frm)
+				refresh_fields(frm)
+				set_html_data(frm)
+			}
+		})
+	}
+});
+
+frappe.ui.form.on('POS Closing Entry Detail', {
+	closing_amount: (frm, cdt, cdn) => {
+		const row = locals[cdt][cdn];
+		frappe.model.set_value(cdt, cdn, "difference", flt(row.expected_amount - row.closing_amount))
+	}
+})
+
+function set_form_data(data, frm) {
+	data.forEach(d => {
+		add_to_pos_transaction(d, frm);
+		frm.doc.grand_total += flt(d.grand_total);
+		frm.doc.net_total += flt(d.net_total);
+		frm.doc.total_quantity += flt(d.total_qty);
+		add_to_payments(d, frm);
+		add_to_taxes(d, frm);
+	});
+}
+
+function add_to_pos_transaction(d, frm) {
+	frm.add_child("pos_transactions", {
+		pos_invoice: d.name,
+		posting_date: d.posting_date,
+		grand_total: d.grand_total,
+		customer: d.customer
+	})
+}
+
+function add_to_payments(d, frm) {
+	d.payments.forEach(p => {
+		const payment = frm.doc.payment_reconciliation.find(pay => pay.mode_of_payment === p.mode_of_payment);
+		if (payment) {
+			payment.expected_amount += flt(p.amount);
+		} else {
+			frm.add_child("payment_reconciliation", {
+				mode_of_payment: p.mode_of_payment,
+				opening_amount: 0,
+				expected_amount: p.amount
+			})
+		}
+	})
+}
+
+function add_to_taxes(d, frm) {
+	d.taxes.forEach(t => {
+		const tax = frm.doc.taxes.find(tx => tx.account_head === t.account_head && tx.rate === t.rate);
+		if (tax) {
+			tax.amount += flt(t.tax_amount); 
+		} else {
+			frm.add_child("taxes", {
+				account_head: t.account_head,
+				rate: t.rate,
+				amount: t.tax_amount
+			})
+		}
+	})
+}
+
+function reset_values(frm) {
+	frm.set_value("pos_transactions", []);
+	frm.set_value("payment_reconciliation", []);
+	frm.set_value("taxes", []);
+	frm.set_value("grand_total", 0);
+	frm.set_value("net_total", 0);
+	frm.set_value("total_quantity", 0);
+}
+
+function refresh_fields(frm) {
+	frm.refresh_field("pos_transactions");
+	frm.refresh_field("payment_reconciliation");
+	frm.refresh_field("taxes");
+	frm.refresh_field("grand_total");
+	frm.refresh_field("net_total");
+	frm.refresh_field("total_quantity");
+}
+
+function set_html_data(frm) {
+	frappe.call({
+		method: "get_payment_reconciliation_details",
+		doc: frm.doc,
+		callback: (r) => {
+			frm.get_field("payment_reconciliation_details").$wrapper.html(r.message);
+		}
+	})
+}
diff --git a/erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry.json b/erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry.json
new file mode 100644
index 0000000..32bca3b
--- /dev/null
+++ b/erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry.json
@@ -0,0 +1,242 @@
+{
+ "actions": [],
+ "autoname": "POS-CLO-.YYYY.-.#####",
+ "creation": "2018-05-28 19:06:40.830043",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "period_start_date",
+  "period_end_date",
+  "column_break_3",
+  "posting_date",
+  "pos_opening_entry",
+  "section_break_5",
+  "company",
+  "column_break_7",
+  "pos_profile",
+  "user",
+  "section_break_12",
+  "pos_transactions",
+  "section_break_9",
+  "payment_reconciliation_details",
+  "section_break_11",
+  "payment_reconciliation",
+  "section_break_13",
+  "grand_total",
+  "net_total",
+  "total_quantity",
+  "column_break_16",
+  "taxes",
+  "section_break_14",
+  "amended_from"
+ ],
+ "fields": [
+  {
+   "fetch_from": "pos_opening_entry.period_start_date",
+   "fieldname": "period_start_date",
+   "fieldtype": "Datetime",
+   "in_list_view": 1,
+   "label": "Period Start Date",
+   "read_only": 1,
+   "reqd": 1
+  },
+  {
+   "default": "Today",
+   "fieldname": "period_end_date",
+   "fieldtype": "Datetime",
+   "in_list_view": 1,
+   "label": "Period End Date",
+   "read_only": 1,
+   "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": "section_break_5",
+   "fieldtype": "Section Break"
+  },
+  {
+   "fieldname": "company",
+   "fieldtype": "Link",
+   "label": "Company",
+   "options": "Company",
+   "reqd": 1
+  },
+  {
+   "fieldname": "column_break_7",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fetch_from": "pos_opening_entry.pos_profile",
+   "fieldname": "pos_profile",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "label": "POS Profile",
+   "options": "POS Profile",
+   "reqd": 1
+  },
+  {
+   "fetch_from": "pos_opening_entry.user",
+   "fieldname": "user",
+   "fieldtype": "Link",
+   "label": "Cashier",
+   "options": "User",
+   "reqd": 1
+  },
+  {
+   "fieldname": "section_break_9",
+   "fieldtype": "Section Break",
+   "read_only": 1
+  },
+  {
+   "depends_on": "eval:doc.docstatus==1",
+   "fieldname": "payment_reconciliation_details",
+   "fieldtype": "HTML"
+  },
+  {
+   "fieldname": "section_break_11",
+   "fieldtype": "Section Break",
+   "label": "Modes of Payment"
+  },
+  {
+   "fieldname": "payment_reconciliation",
+   "fieldtype": "Table",
+   "label": "Payment Reconciliation",
+   "options": "POS Closing Entry Detail"
+  },
+  {
+   "collapsible": 1,
+   "collapsible_depends_on": "eval:doc.docstatus==0",
+   "fieldname": "section_break_13",
+   "fieldtype": "Section Break",
+   "label": "Details"
+  },
+  {
+   "default": "0",
+   "fieldname": "grand_total",
+   "fieldtype": "Currency",
+   "label": "Grand Total",
+   "read_only": 1
+  },
+  {
+   "default": "0",
+   "fieldname": "net_total",
+   "fieldtype": "Currency",
+   "label": "Net Total",
+   "read_only": 1
+  },
+  {
+   "fieldname": "total_quantity",
+   "fieldtype": "Float",
+   "label": "Total Quantity",
+   "read_only": 1
+  },
+  {
+   "fieldname": "column_break_16",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "taxes",
+   "fieldtype": "Table",
+   "label": "Taxes",
+   "options": "POS Closing Entry Taxes",
+   "read_only": 1
+  },
+  {
+   "fieldname": "section_break_12",
+   "fieldtype": "Section Break",
+   "label": "Linked Invoices"
+  },
+  {
+   "fieldname": "section_break_14",
+   "fieldtype": "Section Break"
+  },
+  {
+   "fieldname": "amended_from",
+   "fieldtype": "Link",
+   "label": "Amended From",
+   "no_copy": 1,
+   "options": "POS Closing Entry",
+   "print_hide": 1,
+   "read_only": 1
+  },
+  {
+   "fieldname": "pos_transactions",
+   "fieldtype": "Table",
+   "label": "POS Transactions",
+   "options": "POS Invoice Reference",
+   "reqd": 1
+  },
+  {
+   "fieldname": "pos_opening_entry",
+   "fieldtype": "Link",
+   "label": "POS Opening Entry",
+   "options": "POS Opening Entry",
+   "reqd": 1
+  }
+ ],
+ "is_submittable": 1,
+ "links": [],
+ "modified": "2020-05-29 15:03:22.226113",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "POS Closing Entry",
+ "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,
+   "email": 1,
+   "export": 1,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "Sales Manager",
+   "share": 1,
+   "submit": 1,
+   "write": 1
+  },
+  {
+   "cancel": 1,
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "export": 1,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "Administrator",
+   "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/pos_closing_entry/pos_closing_entry.py b/erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry.py
new file mode 100644
index 0000000..8eb0a22
--- /dev/null
+++ b/erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry.py
@@ -0,0 +1,127 @@
+# -*- 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
+import json
+from frappe import _
+from frappe.model.document import Document
+from frappe.utils import getdate, get_datetime, flt
+from collections import defaultdict
+from erpnext.controllers.taxes_and_totals import get_itemised_tax_breakup_data
+from erpnext.accounts.doctype.pos_invoice_merge_log.pos_invoice_merge_log import merge_pos_invoices
+
+class POSClosingEntry(Document):
+	def validate(self):
+		user = frappe.get_all('POS Closing Entry',
+			filters = { 'user': self.user, 'docstatus': 1 },
+			or_filters = {
+					'period_start_date': ('between', [self.period_start_date, self.period_end_date]),
+					'period_end_date': ('between', [self.period_start_date, self.period_end_date])
+			})
+
+		if user:
+			frappe.throw(_("POS Closing Entry {} against {} between selected period"
+				.format(frappe.bold("already exists"), frappe.bold(self.user))), title=_("Invalid Period"))
+		
+		if frappe.db.get_value("POS Opening Entry", self.pos_opening_entry, "status") != "Open":
+			frappe.throw(_("Selected POS Opening Entry should be open."), title=_("Invalid Opening Entry"))
+
+	def on_submit(self):
+		merge_pos_invoices(self.pos_transactions)
+		opening_entry = frappe.get_doc("POS Opening Entry", self.pos_opening_entry)
+		opening_entry.pos_closing_entry = self.name
+		opening_entry.set_status()
+		opening_entry.save()
+
+	def get_payment_reconciliation_details(self):
+		currency = frappe.get_cached_value('Company', self.company,  "default_currency")
+		return frappe.render_template("erpnext/accounts/doctype/pos_closing_entry/closing_voucher_details.html",
+			{"data": self, "currency": currency})
+
+@frappe.whitelist()
+def get_cashiers(doctype, txt, searchfield, start, page_len, filters):
+	cashiers_list = frappe.get_all("POS Profile User", filters=filters, fields=['user'])
+	return [c['user'] for c in cashiers_list]
+
+@frappe.whitelist()
+def get_pos_invoices(start, end, user):
+	data = frappe.db.sql("""
+	select 
+		name, timestamp(posting_date, posting_time) as "timestamp"
+	from 
+		`tabPOS Invoice`
+	where 
+		owner = %s and docstatus = 1 and 
+		(consolidated_invoice is NULL or consolidated_invoice = '')
+	""", (user), as_dict=1)
+
+	data = list(filter(lambda d: get_datetime(start) <= get_datetime(d.timestamp) <= get_datetime(end), data))
+	# need to get taxes and payments so can't avoid get_doc
+	data = [frappe.get_doc("POS Invoice", d.name).as_dict() for d in data]
+
+	return data
+
+def make_closing_entry_from_opening(opening_entry):
+	closing_entry = frappe.new_doc("POS Closing Entry")
+	closing_entry.pos_opening_entry = opening_entry.name
+	closing_entry.period_start_date = opening_entry.period_start_date
+	closing_entry.period_end_date = frappe.utils.get_datetime()
+	closing_entry.pos_profile = opening_entry.pos_profile
+	closing_entry.user = opening_entry.user
+	closing_entry.company = opening_entry.company
+	closing_entry.grand_total = 0
+	closing_entry.net_total = 0
+	closing_entry.total_quantity = 0
+
+	invoices = get_pos_invoices(closing_entry.period_start_date, closing_entry.period_end_date, closing_entry.user)
+
+	pos_transactions = []
+	taxes = []
+	payments = []
+	for detail in opening_entry.balance_details:
+		payments.append(frappe._dict({
+			'mode_of_payment': detail.mode_of_payment,
+			'opening_amount': detail.opening_amount,
+			'expected_amount': detail.opening_amount
+		}))
+
+	for d in invoices:
+		pos_transactions.append(frappe._dict({
+			'pos_invoice': d.name,
+			'posting_date': d.posting_date,
+			'grand_total': d.grand_total,
+			'customer': d.customer
+		}))
+		closing_entry.grand_total += flt(d.grand_total)
+		closing_entry.net_total += flt(d.net_total)
+		closing_entry.total_quantity += flt(d.total_qty)
+
+		for t in d.taxes:
+			existing_tax = [tx for tx in taxes if tx.account_head == t.account_head and tx.rate == t.rate]
+			if existing_tax:
+				existing_tax[0].amount += flt(t.tax_amount); 
+			else:
+				taxes.append(frappe._dict({
+					'account_head': t.account_head,
+					'rate': t.rate,
+					'amount': t.tax_amount
+				}))
+
+		for p in d.payments:
+			existing_pay = [pay for pay in payments if pay.mode_of_payment == p.mode_of_payment]
+			if existing_pay:
+				existing_pay[0].expected_amount += flt(p.amount);
+			else:
+				payments.append(frappe._dict({
+					'mode_of_payment': p.mode_of_payment,
+					'opening_amount': 0,
+					'expected_amount': p.amount
+				}))
+
+	closing_entry.set("pos_transactions", pos_transactions)
+	closing_entry.set("payment_reconciliation", payments)
+	closing_entry.set("taxes", taxes)
+
+	return closing_entry
diff --git a/erpnext/selling/doctype/pos_closing_voucher/test_pos_closing_voucher.js b/erpnext/accounts/doctype/pos_closing_entry/test_pos_closing_entry.js
similarity index 68%
copy from erpnext/selling/doctype/pos_closing_voucher/test_pos_closing_voucher.js
copy to erpnext/accounts/doctype/pos_closing_entry/test_pos_closing_entry.js
index 7633815..48109b1 100644
--- a/erpnext/selling/doctype/pos_closing_voucher/test_pos_closing_voucher.js
+++ b/erpnext/accounts/doctype/pos_closing_entry/test_pos_closing_entry.js
@@ -2,15 +2,15 @@
 // rename this file from _test_[name] to test_[name] to activate
 // and remove above this line
 
-QUnit.test("test: POS Closing Voucher", function (assert) {
+QUnit.test("test: POS Closing Entry", function (assert) {
 	let done = assert.async();
 
 	// number of asserts
 	assert.expect(1);
 
 	frappe.run_serially([
-		// insert a new POS Closing Voucher
-		() => frappe.tests.make('POS Closing Voucher', [
+		// insert a new POS Closing Entry
+		() => frappe.tests.make('POS Closing Entry', [
 			// values to be set
 			{key: 'value'}
 		]),
diff --git a/erpnext/accounts/doctype/pos_closing_entry/test_pos_closing_entry.py b/erpnext/accounts/doctype/pos_closing_entry/test_pos_closing_entry.py
new file mode 100644
index 0000000..aa6a388
--- /dev/null
+++ b/erpnext/accounts/doctype/pos_closing_entry/test_pos_closing_entry.py
@@ -0,0 +1,64 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
+# See license.txt
+from __future__ import unicode_literals
+import frappe
+import unittest
+from frappe.utils import nowdate
+from erpnext.accounts.doctype.pos_invoice.test_pos_invoice import create_pos_invoice
+from erpnext.accounts.doctype.pos_closing_entry.pos_closing_entry import make_closing_entry_from_opening
+from erpnext.accounts.doctype.pos_opening_entry.test_pos_opening_entry import create_opening_entry
+from erpnext.accounts.doctype.pos_profile.test_pos_profile import make_pos_profile
+
+class TestPOSClosingEntry(unittest.TestCase):
+	def test_pos_closing_entry(self):
+		test_user, pos_profile = init_user_and_profile()
+
+		opening_entry = create_opening_entry(pos_profile, test_user.name)
+
+		pos_inv1 = create_pos_invoice(rate=3500, do_not_submit=1)
+		pos_inv1.append('payments', {
+			'mode_of_payment': 'Cash', 'account': 'Cash - _TC', 'amount': 3500
+		})
+		pos_inv1.submit()
+
+		pos_inv2 = create_pos_invoice(rate=3200, do_not_submit=1)
+		pos_inv2.append('payments', {
+			'mode_of_payment': 'Cash', 'account': 'Cash - _TC', 'amount': 3200
+		})
+		pos_inv2.submit()
+
+		pcv_doc = make_closing_entry_from_opening(opening_entry)
+		payment = pcv_doc.payment_reconciliation[0]
+
+		self.assertEqual(payment.mode_of_payment, 'Cash')
+
+		for d in pcv_doc.payment_reconciliation:
+			if d.mode_of_payment == 'Cash':
+				d.closing_amount = 6700
+
+		pcv_doc.submit()
+
+		self.assertEqual(pcv_doc.total_quantity, 2)
+		self.assertEqual(pcv_doc.net_total, 6700)
+
+		frappe.set_user("Administrator")
+		frappe.db.sql("delete from `tabPOS Profile`")
+
+def init_user_and_profile():
+	user = 'test@example.com'
+	test_user = frappe.get_doc('User', user)
+
+	roles = ("Accounts Manager", "Accounts User", "Sales Manager")
+	test_user.add_roles(*roles)
+	frappe.set_user(user)
+
+	pos_profile = make_pos_profile()
+	pos_profile.append('applicable_for_users', {
+		'default': 1,
+		'user': user
+	})
+
+	pos_profile.save()
+
+	return test_user, pos_profile
\ No newline at end of file
diff --git a/erpnext/accounts/page/pos/__init__.py b/erpnext/accounts/doctype/pos_closing_entry_detail/__init__.py
similarity index 100%
copy from erpnext/accounts/page/pos/__init__.py
copy to erpnext/accounts/doctype/pos_closing_entry_detail/__init__.py
diff --git a/erpnext/accounts/doctype/pos_closing_entry_detail/pos_closing_entry_detail.json b/erpnext/accounts/doctype/pos_closing_entry_detail/pos_closing_entry_detail.json
new file mode 100644
index 0000000..798637a
--- /dev/null
+++ b/erpnext/accounts/doctype/pos_closing_entry_detail/pos_closing_entry_detail.json
@@ -0,0 +1,70 @@
+{
+ "actions": [],
+ "creation": "2018-05-28 19:10:47.580174",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "mode_of_payment",
+  "opening_amount",
+  "closing_amount",
+  "expected_amount",
+  "difference"
+ ],
+ "fields": [
+  {
+   "fieldname": "mode_of_payment",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "label": "Mode of Payment",
+   "options": "Mode of Payment",
+   "reqd": 1
+  },
+  {
+   "fieldname": "expected_amount",
+   "fieldtype": "Currency",
+   "in_list_view": 1,
+   "label": "Expected Amount",
+   "options": "company:company_currency",
+   "read_only": 1,
+   "reqd": 1
+  },
+  {
+   "fieldname": "difference",
+   "fieldtype": "Currency",
+   "in_list_view": 1,
+   "label": "Difference",
+   "options": "company:company_currency",
+   "read_only": 1
+  },
+  {
+   "fieldname": "opening_amount",
+   "fieldtype": "Currency",
+   "in_list_view": 1,
+   "label": "Opening Amount",
+   "options": "company:company_currency",
+   "read_only": 1,
+   "reqd": 1
+  },
+  {
+   "fieldname": "closing_amount",
+   "fieldtype": "Currency",
+   "in_list_view": 1,
+   "label": "Closing Amount",
+   "options": "company:company_currency",
+   "reqd": 1
+  }
+ ],
+ "istable": 1,
+ "links": [],
+ "modified": "2020-05-29 15:03:34.533607",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "POS Closing Entry Detail",
+ "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/selling/doctype/pos_closing_voucher_taxes/pos_closing_voucher_taxes.py b/erpnext/accounts/doctype/pos_closing_entry_detail/pos_closing_entry_detail.py
similarity index 84%
copy from erpnext/selling/doctype/pos_closing_voucher_taxes/pos_closing_voucher_taxes.py
copy to erpnext/accounts/doctype/pos_closing_entry_detail/pos_closing_entry_detail.py
index 87ce842..46b6c77 100644
--- a/erpnext/selling/doctype/pos_closing_voucher_taxes/pos_closing_voucher_taxes.py
+++ b/erpnext/accounts/doctype/pos_closing_entry_detail/pos_closing_entry_detail.py
@@ -5,5 +5,5 @@
 from __future__ import unicode_literals
 from frappe.model.document import Document
 
-class POSClosingVoucherTaxes(Document):
+class POSClosingEntryDetail(Document):
 	pass
diff --git a/erpnext/accounts/page/pos/__init__.py b/erpnext/accounts/doctype/pos_closing_entry_taxes/__init__.py
similarity index 100%
copy from erpnext/accounts/page/pos/__init__.py
copy to erpnext/accounts/doctype/pos_closing_entry_taxes/__init__.py
diff --git a/erpnext/accounts/doctype/pos_closing_entry_taxes/pos_closing_entry_taxes.json b/erpnext/accounts/doctype/pos_closing_entry_taxes/pos_closing_entry_taxes.json
new file mode 100644
index 0000000..42e7d0e
--- /dev/null
+++ b/erpnext/accounts/doctype/pos_closing_entry_taxes/pos_closing_entry_taxes.json
@@ -0,0 +1,48 @@
+{
+ "actions": [],
+ "creation": "2018-05-30 09:11:22.535470",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "account_head",
+  "rate",
+  "amount"
+ ],
+ "fields": [
+  {
+   "fieldname": "rate",
+   "fieldtype": "Percent",
+   "in_list_view": 1,
+   "label": "Rate",
+   "read_only": 1
+  },
+  {
+   "fieldname": "amount",
+   "fieldtype": "Currency",
+   "in_list_view": 1,
+   "label": "Amount",
+   "read_only": 1
+  },
+  {
+   "fieldname": "account_head",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "label": "Account Head",
+   "options": "Account",
+   "read_only": 1
+  }
+ ],
+ "istable": 1,
+ "links": [],
+ "modified": "2020-05-29 15:03:39.872884",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "POS Closing Entry Taxes",
+ "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/selling/doctype/pos_closing_voucher_taxes/pos_closing_voucher_taxes.py b/erpnext/accounts/doctype/pos_closing_entry_taxes/pos_closing_entry_taxes.py
similarity index 84%
rename from erpnext/selling/doctype/pos_closing_voucher_taxes/pos_closing_voucher_taxes.py
rename to erpnext/accounts/doctype/pos_closing_entry_taxes/pos_closing_entry_taxes.py
index 87ce842..f72d9a6 100644
--- a/erpnext/selling/doctype/pos_closing_voucher_taxes/pos_closing_voucher_taxes.py
+++ b/erpnext/accounts/doctype/pos_closing_entry_taxes/pos_closing_entry_taxes.py
@@ -5,5 +5,5 @@
 from __future__ import unicode_literals
 from frappe.model.document import Document
 
-class POSClosingVoucherTaxes(Document):
+class POSClosingEntryTaxes(Document):
 	pass
diff --git a/erpnext/accounts/page/pos/__init__.py b/erpnext/accounts/doctype/pos_invoice/__init__.py
similarity index 100%
copy from erpnext/accounts/page/pos/__init__.py
copy to erpnext/accounts/doctype/pos_invoice/__init__.py
diff --git a/erpnext/accounts/doctype/pos_invoice/pos_invoice.js b/erpnext/accounts/doctype/pos_invoice/pos_invoice.js
new file mode 100644
index 0000000..3be4304
--- /dev/null
+++ b/erpnext/accounts/doctype/pos_invoice/pos_invoice.js
@@ -0,0 +1,205 @@
+// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+{% include 'erpnext/selling/sales_common.js' %};
+
+erpnext.selling.POSInvoiceController = erpnext.selling.SellingController.extend({
+	setup(doc) {
+		this.setup_posting_date_time_check();
+		this._super(doc);
+	},
+
+	onload() {
+		this._super();
+		if(this.frm.doc.__islocal && this.frm.doc.is_pos) {
+			//Load pos profile data on the invoice if the default value of Is POS is 1
+
+			me.frm.script_manager.trigger("is_pos");
+			me.frm.refresh_fields();
+		}
+	},
+
+	refresh(doc) {
+		this._super();
+		if (doc.docstatus == 1 && !doc.is_return) {
+			if(doc.outstanding_amount >= 0 || Math.abs(flt(doc.outstanding_amount)) < flt(doc.grand_total)) {
+				cur_frm.add_custom_button(__('Return'),
+					this.make_sales_return, __('Create'));
+				cur_frm.page.set_inner_btn_group_as_primary(__('Create'));
+			}
+		}
+
+		if (this.frm.doc.is_return) {
+			this.frm.return_print_format = "Sales Invoice Return";
+			cur_frm.set_value('consolidated_invoice', '');
+		}
+	},
+
+	is_pos: function(frm){
+		this.set_pos_data();
+	},
+
+	set_pos_data: function() {
+		if(this.frm.doc.is_pos) {
+			this.frm.set_value("allocate_advances_automatically", 0);
+			if(!this.frm.doc.company) {
+				this.frm.set_value("is_pos", 0);
+				frappe.msgprint(__("Please specify Company to proceed"));
+			} else {
+				var me = this;
+				return this.frm.call({
+					doc: me.frm.doc,
+					method: "set_missing_values",
+					callback: function(r) {
+						if(!r.exc) {
+							if(r.message) {
+								me.frm.pos_print_format = r.message.print_format || "";
+								me.frm.meta.default_print_format = r.message.print_format || "";
+								me.frm.allow_edit_rate = r.message.allow_edit_rate;
+								me.frm.allow_edit_discount = r.message.allow_edit_discount;
+								me.frm.doc.campaign = r.message.campaign;
+								me.frm.allow_print_before_pay = r.message.allow_print_before_pay;
+							}
+							me.frm.script_manager.trigger("update_stock");
+							me.calculate_taxes_and_totals();
+							if(me.frm.doc.taxes_and_charges) {
+								me.frm.script_manager.trigger("taxes_and_charges");
+							}
+							frappe.model.set_default_values(me.frm.doc);
+							me.set_dynamic_labels();
+							
+						}
+					}
+				});
+			}
+		}
+		else this.frm.trigger("refresh");
+	},
+
+	customer() {
+		if (!this.frm.doc.customer) return
+
+		if (this.frm.doc.is_pos){
+			var pos_profile = this.frm.doc.pos_profile;
+		}
+		var me = this;
+		if(this.frm.updating_party_details) return;
+		erpnext.utils.get_party_details(this.frm,
+			"erpnext.accounts.party.get_party_details", {
+				posting_date: this.frm.doc.posting_date,
+				party: this.frm.doc.customer,
+				party_type: "Customer",
+				account: this.frm.doc.debit_to,
+				price_list: this.frm.doc.selling_price_list,
+				pos_profile: pos_profile
+			}, function() {
+				me.apply_pricing_rule();
+			});
+	},
+
+	amount: function(){
+		this.write_off_outstanding_amount_automatically()
+	},
+
+	change_amount: function(){
+		if(this.frm.doc.paid_amount > this.frm.doc.grand_total){
+			this.calculate_write_off_amount();
+		}else {
+			this.frm.set_value("change_amount", 0.0);
+			this.frm.set_value("base_change_amount", 0.0);
+		}
+
+		this.frm.refresh_fields();
+	},
+
+	loyalty_amount: function(){
+		this.calculate_outstanding_amount();
+		this.frm.refresh_field("outstanding_amount");
+		this.frm.refresh_field("paid_amount");
+		this.frm.refresh_field("base_paid_amount");
+	},
+
+	write_off_outstanding_amount_automatically: function() {
+		if(cint(this.frm.doc.write_off_outstanding_amount_automatically)) {
+			frappe.model.round_floats_in(this.frm.doc, ["grand_total", "paid_amount"]);
+			// this will make outstanding amount 0
+			this.frm.set_value("write_off_amount",
+				flt(this.frm.doc.grand_total - this.frm.doc.paid_amount - this.frm.doc.total_advance, precision("write_off_amount"))
+			);
+			this.frm.toggle_enable("write_off_amount", false);
+
+		} else {
+			this.frm.toggle_enable("write_off_amount", true);
+		}
+
+		this.calculate_outstanding_amount(false);
+		this.frm.refresh_fields();
+	},
+
+	make_sales_return: function() {
+		frappe.model.open_mapped_doc({
+			method: "erpnext.accounts.doctype.pos_invoice.pos_invoice.make_sales_return",
+			frm: cur_frm
+		})
+	},
+})
+
+$.extend(cur_frm.cscript, new erpnext.selling.POSInvoiceController({ frm: cur_frm }))
+
+frappe.ui.form.on('POS Invoice', {
+	redeem_loyalty_points: function(frm) {
+		frm.events.get_loyalty_details(frm);
+	},
+
+	loyalty_points: function(frm) {
+		if (frm.redemption_conversion_factor) {
+			frm.events.set_loyalty_points(frm);
+		} else {
+			frappe.call({
+				method: "erpnext.accounts.doctype.loyalty_program.loyalty_program.get_redeemption_factor",
+				args: {
+					"loyalty_program": frm.doc.loyalty_program
+				},
+				callback: function(r) {
+					if (r) {
+						frm.redemption_conversion_factor = r.message;
+						frm.events.set_loyalty_points(frm);
+					}
+				}
+			});
+		}
+	},
+
+	get_loyalty_details: function(frm) {
+		if (frm.doc.customer && frm.doc.redeem_loyalty_points) {
+			frappe.call({
+				method: "erpnext.accounts.doctype.loyalty_program.loyalty_program.get_loyalty_program_details",
+				args: {
+					"customer": frm.doc.customer,
+					"loyalty_program": frm.doc.loyalty_program,
+					"expiry_date": frm.doc.posting_date,
+					"company": frm.doc.company
+				},
+				callback: function(r) {
+					if (r) {
+						frm.set_value("loyalty_redemption_account", r.message.expense_account);
+						frm.set_value("loyalty_redemption_cost_center", r.message.cost_center);
+						frm.redemption_conversion_factor = r.message.conversion_factor;
+					}
+				}
+			});
+		}
+	},
+
+	set_loyalty_points: function(frm) {
+		if (frm.redemption_conversion_factor) {
+			let loyalty_amount = flt(frm.redemption_conversion_factor*flt(frm.doc.loyalty_points), precision("loyalty_amount"));
+			var remaining_amount = flt(frm.doc.grand_total) - flt(frm.doc.total_advance) - flt(frm.doc.write_off_amount);
+			if (frm.doc.grand_total && (remaining_amount < loyalty_amount)) {
+				let redeemable_points = parseInt(remaining_amount/frm.redemption_conversion_factor);
+				frappe.throw(__("You can only redeem max {0} points in this order.",[redeemable_points]));
+			}
+			frm.set_value("loyalty_amount", loyalty_amount);
+		}
+	}
+});
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/pos_invoice/pos_invoice.json b/erpnext/accounts/doctype/pos_invoice/pos_invoice.json
new file mode 100644
index 0000000..2a2e3df
--- /dev/null
+++ b/erpnext/accounts/doctype/pos_invoice/pos_invoice.json
@@ -0,0 +1,1637 @@
+{
+ "actions": [],
+ "allow_import": 1,
+ "autoname": "naming_series:",
+ "creation": "2020-01-24 15:29:29.933693",
+ "doctype": "DocType",
+ "engine": "InnoDB",
+ "field_order": [
+  "customer_section",
+  "title",
+  "naming_series",
+  "customer",
+  "customer_name",
+  "tax_id",
+  "is_pos",
+  "pos_profile",
+  "offline_pos_name",
+  "is_return",
+  "consolidated_invoice",
+  "column_break1",
+  "company",
+  "posting_date",
+  "posting_time",
+  "set_posting_time",
+  "due_date",
+  "amended_from",
+  "returns",
+  "return_against",
+  "column_break_21",
+  "update_billed_amount_in_sales_order",
+  "accounting_dimensions_section",
+  "project",
+  "dimension_col_break",
+  "cost_center",
+  "customer_po_details",
+  "po_no",
+  "column_break_23",
+  "po_date",
+  "address_and_contact",
+  "customer_address",
+  "address_display",
+  "contact_person",
+  "contact_display",
+  "contact_mobile",
+  "contact_email",
+  "territory",
+  "col_break4",
+  "shipping_address_name",
+  "shipping_address",
+  "company_address",
+  "company_address_display",
+  "currency_and_price_list",
+  "currency",
+  "conversion_rate",
+  "column_break2",
+  "selling_price_list",
+  "price_list_currency",
+  "plc_conversion_rate",
+  "ignore_pricing_rule",
+  "sec_warehouse",
+  "set_warehouse",
+  "items_section",
+  "update_stock",
+  "scan_barcode",
+  "items",
+  "pricing_rule_details",
+  "pricing_rules",
+  "packing_list",
+  "packed_items",
+  "product_bundle_help",
+  "time_sheet_list",
+  "timesheets",
+  "total_billing_amount",
+  "section_break_30",
+  "total_qty",
+  "base_total",
+  "base_net_total",
+  "column_break_32",
+  "total",
+  "net_total",
+  "total_net_weight",
+  "taxes_section",
+  "taxes_and_charges",
+  "column_break_38",
+  "shipping_rule",
+  "tax_category",
+  "section_break_40",
+  "taxes",
+  "sec_tax_breakup",
+  "other_charges_calculation",
+  "section_break_43",
+  "base_total_taxes_and_charges",
+  "column_break_47",
+  "total_taxes_and_charges",
+  "loyalty_points_redemption",
+  "loyalty_points",
+  "loyalty_amount",
+  "redeem_loyalty_points",
+  "column_break_77",
+  "loyalty_program",
+  "loyalty_redemption_account",
+  "loyalty_redemption_cost_center",
+  "section_break_49",
+  "apply_discount_on",
+  "base_discount_amount",
+  "column_break_51",
+  "additional_discount_percentage",
+  "discount_amount",
+  "totals",
+  "base_grand_total",
+  "base_rounding_adjustment",
+  "base_rounded_total",
+  "base_in_words",
+  "column_break5",
+  "grand_total",
+  "rounding_adjustment",
+  "rounded_total",
+  "in_words",
+  "total_advance",
+  "outstanding_amount",
+  "advances_section",
+  "allocate_advances_automatically",
+  "get_advances",
+  "advances",
+  "payment_schedule_section",
+  "payment_terms_template",
+  "payment_schedule",
+  "payments_section",
+  "cash_bank_account",
+  "payments",
+  "section_break_84",
+  "base_paid_amount",
+  "column_break_86",
+  "paid_amount",
+  "section_break_88",
+  "base_change_amount",
+  "column_break_90",
+  "change_amount",
+  "account_for_change_amount",
+  "column_break4",
+  "write_off_amount",
+  "base_write_off_amount",
+  "write_off_outstanding_amount_automatically",
+  "column_break_74",
+  "write_off_account",
+  "write_off_cost_center",
+  "terms_section_break",
+  "tc_name",
+  "terms",
+  "edit_printing_settings",
+  "letter_head",
+  "group_same_items",
+  "language",
+  "column_break_84",
+  "select_print_heading",
+  "more_information",
+  "inter_company_invoice_reference",
+  "customer_group",
+  "campaign",
+  "is_discounted",
+  "col_break23",
+  "status",
+  "source",
+  "more_info",
+  "debit_to",
+  "party_account_currency",
+  "is_opening",
+  "c_form_applicable",
+  "c_form_no",
+  "column_break8",
+  "remarks",
+  "sales_team_section_break",
+  "sales_partner",
+  "column_break10",
+  "commission_rate",
+  "total_commission",
+  "section_break2",
+  "sales_team",
+  "subscription_section",
+  "from_date",
+  "to_date",
+  "column_break_140",
+  "auto_repeat",
+  "update_auto_repeat_reference",
+  "against_income_account",
+  "pos_total_qty"
+ ],
+ "fields": [
+  {
+   "fieldname": "customer_section",
+   "fieldtype": "Section Break",
+   "options": "fa fa-user"
+  },
+  {
+   "allow_on_submit": 1,
+   "default": "{customer_name}",
+   "fieldname": "title",
+   "fieldtype": "Data",
+   "hidden": 1,
+   "label": "Title",
+   "no_copy": 1,
+   "print_hide": 1
+  },
+  {
+   "bold": 1,
+   "fieldname": "naming_series",
+   "fieldtype": "Select",
+   "label": "Series",
+   "no_copy": 1,
+   "oldfieldname": "naming_series",
+   "oldfieldtype": "Select",
+   "options": "ACC-PSINV-.YYYY.-",
+   "print_hide": 1,
+   "reqd": 1,
+   "set_only_once": 1
+  },
+  {
+   "bold": 1,
+   "fieldname": "customer",
+   "fieldtype": "Link",
+   "in_standard_filter": 1,
+   "label": "Customer",
+   "oldfieldname": "customer",
+   "oldfieldtype": "Link",
+   "options": "Customer",
+   "print_hide": 1,
+   "search_index": 1
+  },
+  {
+   "bold": 1,
+   "depends_on": "customer",
+   "fetch_from": "customer.customer_name",
+   "fieldname": "customer_name",
+   "fieldtype": "Data",
+   "in_global_search": 1,
+   "label": "Customer Name",
+   "oldfieldname": "customer_name",
+   "oldfieldtype": "Data",
+   "read_only": 1
+  },
+  {
+   "fieldname": "tax_id",
+   "fieldtype": "Data",
+   "label": "Tax Id",
+   "print_hide": 1,
+   "read_only": 1
+  },
+  {
+   "default": "1",
+   "fieldname": "is_pos",
+   "fieldtype": "Check",
+   "label": "Include Payment (POS)",
+   "oldfieldname": "is_pos",
+   "oldfieldtype": "Check",
+   "print_hide": 1,
+   "read_only": 1,
+   "reqd": 1
+  },
+  {
+   "depends_on": "is_pos",
+   "fieldname": "pos_profile",
+   "fieldtype": "Link",
+   "label": "POS Profile",
+   "options": "POS Profile",
+   "print_hide": 1
+  },
+  {
+   "fieldname": "offline_pos_name",
+   "fieldtype": "Data",
+   "hidden": 1,
+   "label": "Offline POS Name",
+   "print_hide": 1,
+   "read_only": 1
+  },
+  {
+   "allow_on_submit": 1,
+   "default": "0",
+   "fieldname": "is_return",
+   "fieldtype": "Check",
+   "label": "Is Return (Credit Note)",
+   "no_copy": 1,
+   "print_hide": 1
+  },
+  {
+   "fieldname": "column_break1",
+   "fieldtype": "Column Break",
+   "oldfieldtype": "Column Break"
+  },
+  {
+   "fieldname": "company",
+   "fieldtype": "Link",
+   "in_standard_filter": 1,
+   "label": "Company",
+   "oldfieldname": "company",
+   "oldfieldtype": "Link",
+   "options": "Company",
+   "print_hide": 1,
+   "remember_last_selected_value": 1,
+   "reqd": 1
+  },
+  {
+   "bold": 1,
+   "default": "Today",
+   "fieldname": "posting_date",
+   "fieldtype": "Date",
+   "label": "Date",
+   "no_copy": 1,
+   "oldfieldname": "posting_date",
+   "oldfieldtype": "Date",
+   "reqd": 1,
+   "search_index": 1
+  },
+  {
+   "fieldname": "posting_time",
+   "fieldtype": "Time",
+   "label": "Posting Time",
+   "no_copy": 1,
+   "oldfieldname": "posting_time",
+   "oldfieldtype": "Time",
+   "print_hide": 1
+  },
+  {
+   "default": "0",
+   "depends_on": "eval:doc.docstatus==0",
+   "fieldname": "set_posting_time",
+   "fieldtype": "Check",
+   "label": "Edit Posting Date and Time",
+   "print_hide": 1
+  },
+  {
+   "fieldname": "due_date",
+   "fieldtype": "Date",
+   "label": "Payment Due Date",
+   "no_copy": 1,
+   "oldfieldname": "due_date",
+   "oldfieldtype": "Date"
+  },
+  {
+   "fieldname": "amended_from",
+   "fieldtype": "Link",
+   "ignore_user_permissions": 1,
+   "label": "Amended From",
+   "no_copy": 1,
+   "oldfieldname": "amended_from",
+   "oldfieldtype": "Link",
+   "options": "POS Invoice",
+   "print_hide": 1,
+   "read_only": 1
+  },
+  {
+   "depends_on": "return_against",
+   "fieldname": "returns",
+   "fieldtype": "Section Break",
+   "label": "Returns"
+  },
+  {
+   "depends_on": "return_against",
+   "fieldname": "return_against",
+   "fieldtype": "Link",
+   "label": "Return Against POS Invoice",
+   "no_copy": 1,
+   "options": "POS Invoice",
+   "print_hide": 1,
+   "read_only": 1
+  },
+  {
+   "fieldname": "column_break_21",
+   "fieldtype": "Column Break"
+  },
+  {
+   "default": "0",
+   "depends_on": "eval: doc.is_return && doc.return_against",
+   "fieldname": "update_billed_amount_in_sales_order",
+   "fieldtype": "Check",
+   "label": "Update Billed Amount in Sales Order"
+  },
+  {
+   "collapsible": 1,
+   "fieldname": "accounting_dimensions_section",
+   "fieldtype": "Section Break",
+   "label": "Accounting Dimensions"
+  },
+  {
+   "fieldname": "project",
+   "fieldtype": "Link",
+   "in_global_search": 1,
+   "label": "Project",
+   "oldfieldname": "project_name",
+   "oldfieldtype": "Link",
+   "options": "Project",
+   "print_hide": 1
+  },
+  {
+   "fieldname": "dimension_col_break",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "cost_center",
+   "fieldtype": "Link",
+   "label": "Cost Center",
+   "options": "Cost Center"
+  },
+  {
+   "collapsible": 1,
+   "collapsible_depends_on": "po_no",
+   "fieldname": "customer_po_details",
+   "fieldtype": "Section Break",
+   "label": "Customer PO Details"
+  },
+  {
+   "allow_on_submit": 1,
+   "fieldname": "po_no",
+   "fieldtype": "Data",
+   "label": "Customer's Purchase Order",
+   "no_copy": 1,
+   "print_hide": 1
+  },
+  {
+   "fieldname": "column_break_23",
+   "fieldtype": "Column Break"
+  },
+  {
+   "allow_on_submit": 1,
+   "fieldname": "po_date",
+   "fieldtype": "Date",
+   "label": "Customer's Purchase Order Date"
+  },
+  {
+   "collapsible": 1,
+   "fieldname": "address_and_contact",
+   "fieldtype": "Section Break",
+   "label": "Address and Contact"
+  },
+  {
+   "fieldname": "customer_address",
+   "fieldtype": "Link",
+   "label": "Customer Address",
+   "options": "Address",
+   "print_hide": 1
+  },
+  {
+   "fieldname": "address_display",
+   "fieldtype": "Small Text",
+   "label": "Address",
+   "read_only": 1
+  },
+  {
+   "fieldname": "contact_person",
+   "fieldtype": "Link",
+   "in_global_search": 1,
+   "label": "Contact Person",
+   "options": "Contact",
+   "print_hide": 1
+  },
+  {
+   "fieldname": "contact_display",
+   "fieldtype": "Small Text",
+   "label": "Contact",
+   "read_only": 1
+  },
+  {
+   "fieldname": "contact_mobile",
+   "fieldtype": "Small Text",
+   "hidden": 1,
+   "label": "Mobile No",
+   "read_only": 1
+  },
+  {
+   "fieldname": "contact_email",
+   "fieldtype": "Data",
+   "hidden": 1,
+   "label": "Contact Email",
+   "options": "Email",
+   "print_hide": 1,
+   "read_only": 1
+  },
+  {
+   "fieldname": "territory",
+   "fieldtype": "Link",
+   "label": "Territory",
+   "options": "Territory",
+   "print_hide": 1
+  },
+  {
+   "fieldname": "col_break4",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "shipping_address_name",
+   "fieldtype": "Link",
+   "label": "Shipping Address Name",
+   "options": "Address",
+   "print_hide": 1
+  },
+  {
+   "fieldname": "shipping_address",
+   "fieldtype": "Small Text",
+   "label": "Shipping Address",
+   "print_hide": 1,
+   "read_only": 1
+  },
+  {
+   "fieldname": "company_address",
+   "fieldtype": "Link",
+   "label": "Company Address Name",
+   "options": "Address",
+   "print_hide": 1
+  },
+  {
+   "fieldname": "company_address_display",
+   "fieldtype": "Small Text",
+   "hidden": 1,
+   "label": "Company Address",
+   "print_hide": 1,
+   "read_only": 1
+  },
+  {
+   "collapsible": 1,
+   "depends_on": "customer",
+   "fieldname": "currency_and_price_list",
+   "fieldtype": "Section Break",
+   "label": "Currency and Price List"
+  },
+  {
+   "fieldname": "currency",
+   "fieldtype": "Link",
+   "label": "Currency",
+   "oldfieldname": "currency",
+   "oldfieldtype": "Select",
+   "options": "Currency",
+   "print_hide": 1,
+   "reqd": 1
+  },
+  {
+   "description": "Rate at which Customer Currency is converted to customer's base currency",
+   "fieldname": "conversion_rate",
+   "fieldtype": "Float",
+   "label": "Exchange Rate",
+   "oldfieldname": "conversion_rate",
+   "oldfieldtype": "Currency",
+   "precision": "9",
+   "print_hide": 1,
+   "reqd": 1
+  },
+  {
+   "fieldname": "column_break2",
+   "fieldtype": "Column Break",
+   "width": "50%"
+  },
+  {
+   "fieldname": "selling_price_list",
+   "fieldtype": "Link",
+   "label": "Price List",
+   "oldfieldname": "price_list_name",
+   "oldfieldtype": "Select",
+   "options": "Price List",
+   "print_hide": 1,
+   "reqd": 1
+  },
+  {
+   "fieldname": "price_list_currency",
+   "fieldtype": "Link",
+   "label": "Price List Currency",
+   "options": "Currency",
+   "print_hide": 1,
+   "read_only": 1,
+   "reqd": 1
+  },
+  {
+   "description": "Rate at which Price list currency is converted to customer's base currency",
+   "fieldname": "plc_conversion_rate",
+   "fieldtype": "Float",
+   "label": "Price List Exchange Rate",
+   "precision": "9",
+   "print_hide": 1,
+   "reqd": 1
+  },
+  {
+   "default": "0",
+   "fieldname": "ignore_pricing_rule",
+   "fieldtype": "Check",
+   "label": "Ignore Pricing Rule",
+   "no_copy": 1,
+   "permlevel": 1,
+   "print_hide": 1
+  },
+  {
+   "fieldname": "sec_warehouse",
+   "fieldtype": "Section Break"
+  },
+  {
+   "depends_on": "update_stock",
+   "fieldname": "set_warehouse",
+   "fieldtype": "Link",
+   "label": "Set Source Warehouse",
+   "options": "Warehouse",
+   "print_hide": 1
+  },
+  {
+   "fieldname": "items_section",
+   "fieldtype": "Section Break",
+   "oldfieldtype": "Section Break",
+   "options": "fa fa-shopping-cart"
+  },
+  {
+   "default": "0",
+   "fieldname": "update_stock",
+   "fieldtype": "Check",
+   "label": "Update Stock",
+   "oldfieldname": "update_stock",
+   "oldfieldtype": "Check",
+   "print_hide": 1
+  },
+  {
+   "fieldname": "scan_barcode",
+   "fieldtype": "Data",
+   "label": "Scan Barcode"
+  },
+  {
+   "allow_bulk_edit": 1,
+   "fieldname": "items",
+   "fieldtype": "Table",
+   "label": "Items",
+   "oldfieldname": "entries",
+   "oldfieldtype": "Table",
+   "options": "POS Invoice Item",
+   "reqd": 1
+  },
+  {
+   "fieldname": "pricing_rule_details",
+   "fieldtype": "Section Break",
+   "label": "Pricing Rules"
+  },
+  {
+   "fieldname": "pricing_rules",
+   "fieldtype": "Table",
+   "label": "Pricing Rule Detail",
+   "options": "Pricing Rule Detail",
+   "read_only": 1
+  },
+  {
+   "fieldname": "packing_list",
+   "fieldtype": "Section Break",
+   "label": "Packing List",
+   "options": "fa fa-suitcase",
+   "print_hide": 1
+  },
+  {
+   "fieldname": "packed_items",
+   "fieldtype": "Table",
+   "label": "Packed Items",
+   "options": "Packed Item",
+   "print_hide": 1
+  },
+  {
+   "fieldname": "product_bundle_help",
+   "fieldtype": "HTML",
+   "label": "Product Bundle Help",
+   "print_hide": 1
+  },
+  {
+   "collapsible": 1,
+   "collapsible_depends_on": "eval:doc.total_billing_amount > 0",
+   "fieldname": "time_sheet_list",
+   "fieldtype": "Section Break",
+   "label": "Time Sheet List"
+  },
+  {
+   "fieldname": "timesheets",
+   "fieldtype": "Table",
+   "label": "Time Sheets",
+   "options": "Sales Invoice Timesheet",
+   "print_hide": 1
+  },
+  {
+   "default": "0",
+   "fieldname": "total_billing_amount",
+   "fieldtype": "Currency",
+   "label": "Total Billing Amount",
+   "print_hide": 1,
+   "read_only": 1
+  },
+  {
+   "fieldname": "section_break_30",
+   "fieldtype": "Section Break"
+  },
+  {
+   "fieldname": "total_qty",
+   "fieldtype": "Float",
+   "label": "Total Quantity",
+   "read_only": 1
+  },
+  {
+   "fieldname": "base_total",
+   "fieldtype": "Currency",
+   "label": "Total (Company Currency)",
+   "options": "Company:company:default_currency",
+   "print_hide": 1,
+   "read_only": 1
+  },
+  {
+   "fieldname": "base_net_total",
+   "fieldtype": "Currency",
+   "label": "Net Total (Company Currency)",
+   "oldfieldname": "net_total",
+   "oldfieldtype": "Currency",
+   "options": "Company:company:default_currency",
+   "print_hide": 1,
+   "read_only": 1,
+   "reqd": 1
+  },
+  {
+   "fieldname": "column_break_32",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "total",
+   "fieldtype": "Currency",
+   "label": "Total",
+   "options": "currency",
+   "read_only": 1
+  },
+  {
+   "fieldname": "net_total",
+   "fieldtype": "Currency",
+   "label": "Net Total",
+   "options": "currency",
+   "print_hide": 1,
+   "read_only": 1
+  },
+  {
+   "fieldname": "total_net_weight",
+   "fieldtype": "Float",
+   "label": "Total Net Weight",
+   "print_hide": 1,
+   "read_only": 1
+  },
+  {
+   "fieldname": "taxes_section",
+   "fieldtype": "Section Break",
+   "oldfieldtype": "Section Break",
+   "options": "fa fa-money"
+  },
+  {
+   "fieldname": "taxes_and_charges",
+   "fieldtype": "Link",
+   "label": "Sales Taxes and Charges Template",
+   "oldfieldname": "charge",
+   "oldfieldtype": "Link",
+   "options": "Sales Taxes and Charges Template",
+   "print_hide": 1
+  },
+  {
+   "fieldname": "column_break_38",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "shipping_rule",
+   "fieldtype": "Link",
+   "label": "Shipping Rule",
+   "oldfieldtype": "Button",
+   "options": "Shipping Rule",
+   "print_hide": 1
+  },
+  {
+   "fieldname": "tax_category",
+   "fieldtype": "Link",
+   "label": "Tax Category",
+   "options": "Tax Category",
+   "print_hide": 1
+  },
+  {
+   "fieldname": "section_break_40",
+   "fieldtype": "Section Break"
+  },
+  {
+   "fieldname": "taxes",
+   "fieldtype": "Table",
+   "label": "Sales Taxes and Charges",
+   "oldfieldname": "other_charges",
+   "oldfieldtype": "Table",
+   "options": "Sales Taxes and Charges"
+  },
+  {
+   "collapsible": 1,
+   "fieldname": "sec_tax_breakup",
+   "fieldtype": "Section Break",
+   "label": "Tax Breakup"
+  },
+  {
+   "fieldname": "other_charges_calculation",
+   "fieldtype": "Long Text",
+   "label": "Taxes and Charges Calculation",
+   "no_copy": 1,
+   "oldfieldtype": "HTML",
+   "print_hide": 1,
+   "read_only": 1
+  },
+  {
+   "fieldname": "section_break_43",
+   "fieldtype": "Section Break"
+  },
+  {
+   "fieldname": "base_total_taxes_and_charges",
+   "fieldtype": "Currency",
+   "label": "Total Taxes and Charges (Company Currency)",
+   "oldfieldname": "other_charges_total",
+   "oldfieldtype": "Currency",
+   "options": "Company:company:default_currency",
+   "print_hide": 1,
+   "read_only": 1
+  },
+  {
+   "fieldname": "column_break_47",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "total_taxes_and_charges",
+   "fieldtype": "Currency",
+   "label": "Total Taxes and Charges",
+   "options": "currency",
+   "print_hide": 1,
+   "read_only": 1
+  },
+  {
+   "collapsible": 1,
+   "fieldname": "loyalty_points_redemption",
+   "fieldtype": "Section Break",
+   "label": "Loyalty Points Redemption"
+  },
+  {
+   "depends_on": "redeem_loyalty_points",
+   "fieldname": "loyalty_points",
+   "fieldtype": "Int",
+   "label": "Loyalty Points",
+   "no_copy": 1,
+   "print_hide": 1
+  },
+  {
+   "depends_on": "redeem_loyalty_points",
+   "fieldname": "loyalty_amount",
+   "fieldtype": "Currency",
+   "label": "Loyalty Amount",
+   "no_copy": 1,
+   "options": "Company:company:default_currency",
+   "print_hide": 1,
+   "read_only": 1
+  },
+  {
+   "default": "0",
+   "fieldname": "redeem_loyalty_points",
+   "fieldtype": "Check",
+   "label": "Redeem Loyalty Points",
+   "no_copy": 1,
+   "print_hide": 1
+  },
+  {
+   "fieldname": "column_break_77",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fetch_from": "customer.loyalty_program",
+   "fieldname": "loyalty_program",
+   "fieldtype": "Link",
+   "label": "Loyalty Program",
+   "no_copy": 1,
+   "options": "Loyalty Program",
+   "print_hide": 1,
+   "read_only": 1
+  },
+  {
+   "depends_on": "redeem_loyalty_points",
+   "fieldname": "loyalty_redemption_account",
+   "fieldtype": "Link",
+   "label": "Redemption Account",
+   "no_copy": 1,
+   "options": "Account"
+  },
+  {
+   "depends_on": "redeem_loyalty_points",
+   "fieldname": "loyalty_redemption_cost_center",
+   "fieldtype": "Link",
+   "label": "Redemption Cost Center",
+   "no_copy": 1,
+   "options": "Cost Center"
+  },
+  {
+   "collapsible": 1,
+   "collapsible_depends_on": "discount_amount",
+   "fieldname": "section_break_49",
+   "fieldtype": "Section Break",
+   "label": "Additional Discount"
+  },
+  {
+   "default": "Grand Total",
+   "fieldname": "apply_discount_on",
+   "fieldtype": "Select",
+   "label": "Apply Additional Discount On",
+   "options": "\nGrand Total\nNet Total",
+   "print_hide": 1
+  },
+  {
+   "fieldname": "base_discount_amount",
+   "fieldtype": "Currency",
+   "label": "Additional Discount Amount (Company Currency)",
+   "options": "Company:company:default_currency",
+   "print_hide": 1,
+   "read_only": 1
+  },
+  {
+   "fieldname": "column_break_51",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "additional_discount_percentage",
+   "fieldtype": "Float",
+   "label": "Additional Discount Percentage",
+   "print_hide": 1
+  },
+  {
+   "fieldname": "discount_amount",
+   "fieldtype": "Currency",
+   "label": "Additional Discount Amount",
+   "options": "currency",
+   "print_hide": 1
+  },
+  {
+   "fieldname": "totals",
+   "fieldtype": "Section Break",
+   "oldfieldtype": "Section Break",
+   "options": "fa fa-money",
+   "print_hide": 1
+  },
+  {
+   "fieldname": "base_grand_total",
+   "fieldtype": "Currency",
+   "label": "Grand Total (Company Currency)",
+   "oldfieldname": "grand_total",
+   "oldfieldtype": "Currency",
+   "options": "Company:company:default_currency",
+   "print_hide": 1,
+   "read_only": 1,
+   "reqd": 1
+  },
+  {
+   "fieldname": "base_rounding_adjustment",
+   "fieldtype": "Currency",
+   "label": "Rounding Adjustment (Company Currency)",
+   "no_copy": 1,
+   "options": "Company:company:default_currency",
+   "print_hide": 1,
+   "read_only": 1
+  },
+  {
+   "fieldname": "base_rounded_total",
+   "fieldtype": "Currency",
+   "label": "Rounded Total (Company Currency)",
+   "oldfieldname": "rounded_total",
+   "oldfieldtype": "Currency",
+   "options": "Company:company:default_currency",
+   "print_hide": 1,
+   "read_only": 1
+  },
+  {
+   "description": "In Words will be visible once you save the Sales Invoice.",
+   "fieldname": "base_in_words",
+   "fieldtype": "Data",
+   "label": "In Words (Company Currency)",
+   "oldfieldname": "in_words",
+   "oldfieldtype": "Data",
+   "print_hide": 1,
+   "read_only": 1
+  },
+  {
+   "fieldname": "column_break5",
+   "fieldtype": "Column Break",
+   "oldfieldtype": "Column Break",
+   "print_hide": 1,
+   "width": "50%"
+  },
+  {
+   "bold": 1,
+   "fieldname": "grand_total",
+   "fieldtype": "Currency",
+   "in_list_view": 1,
+   "label": "Grand Total",
+   "oldfieldname": "grand_total_export",
+   "oldfieldtype": "Currency",
+   "options": "currency",
+   "read_only": 1,
+   "reqd": 1
+  },
+  {
+   "fieldname": "rounding_adjustment",
+   "fieldtype": "Currency",
+   "label": "Rounding Adjustment",
+   "no_copy": 1,
+   "options": "currency",
+   "print_hide": 1,
+   "read_only": 1
+  },
+  {
+   "bold": 1,
+   "fieldname": "rounded_total",
+   "fieldtype": "Currency",
+   "label": "Rounded Total",
+   "oldfieldname": "rounded_total_export",
+   "oldfieldtype": "Currency",
+   "options": "currency",
+   "read_only": 1
+  },
+  {
+   "fieldname": "in_words",
+   "fieldtype": "Data",
+   "label": "In Words",
+   "oldfieldname": "in_words_export",
+   "oldfieldtype": "Data",
+   "print_hide": 1,
+   "read_only": 1
+  },
+  {
+   "fieldname": "total_advance",
+   "fieldtype": "Currency",
+   "label": "Total Advance",
+   "oldfieldname": "total_advance",
+   "oldfieldtype": "Currency",
+   "options": "party_account_currency",
+   "print_hide": 1,
+   "read_only": 1
+  },
+  {
+   "fieldname": "outstanding_amount",
+   "fieldtype": "Currency",
+   "label": "Outstanding Amount",
+   "no_copy": 1,
+   "oldfieldname": "outstanding_amount",
+   "oldfieldtype": "Currency",
+   "options": "party_account_currency",
+   "print_hide": 1,
+   "read_only": 1
+  },
+  {
+   "collapsible": 1,
+   "collapsible_depends_on": "advances",
+   "fieldname": "advances_section",
+   "fieldtype": "Section Break",
+   "label": "Advance Payments",
+   "oldfieldtype": "Section Break",
+   "options": "fa fa-money",
+   "print_hide": 1
+  },
+  {
+   "default": "0",
+   "fieldname": "allocate_advances_automatically",
+   "fieldtype": "Check",
+   "label": "Allocate Advances Automatically (FIFO)"
+  },
+  {
+   "depends_on": "eval:!doc.allocate_advances_automatically",
+   "fieldname": "get_advances",
+   "fieldtype": "Button",
+   "label": "Get Advances Received",
+   "options": "set_advances"
+  },
+  {
+   "fieldname": "advances",
+   "fieldtype": "Table",
+   "label": "Advances",
+   "oldfieldname": "advance_adjustment_details",
+   "oldfieldtype": "Table",
+   "options": "Sales Invoice Advance",
+   "print_hide": 1
+  },
+  {
+   "collapsible": 1,
+   "collapsible_depends_on": "eval:(!doc.is_pos && !doc.is_return)",
+   "fieldname": "payment_schedule_section",
+   "fieldtype": "Section Break",
+   "label": "Payment Terms"
+  },
+  {
+   "depends_on": "eval:(!doc.is_pos && !doc.is_return)",
+   "fieldname": "payment_terms_template",
+   "fieldtype": "Link",
+   "label": "Payment Terms Template",
+   "no_copy": 1,
+   "options": "Payment Terms Template",
+   "print_hide": 1
+  },
+  {
+   "depends_on": "eval:(!doc.is_pos && !doc.is_return)",
+   "fieldname": "payment_schedule",
+   "fieldtype": "Table",
+   "label": "Payment Schedule",
+   "no_copy": 1,
+   "options": "Payment Schedule",
+   "print_hide": 1
+  },
+  {
+   "depends_on": "eval:doc.is_pos===1||(doc.advances && doc.advances.length>0)",
+   "fieldname": "payments_section",
+   "fieldtype": "Section Break",
+   "label": "Payments",
+   "options": "fa fa-money"
+  },
+  {
+   "depends_on": "is_pos",
+   "fieldname": "cash_bank_account",
+   "fieldtype": "Link",
+   "hidden": 1,
+   "label": "Cash/Bank Account",
+   "oldfieldname": "cash_bank_account",
+   "oldfieldtype": "Link",
+   "options": "Account",
+   "print_hide": 1
+  },
+  {
+   "depends_on": "eval:doc.is_pos===1",
+   "fieldname": "payments",
+   "fieldtype": "Table",
+   "label": "Sales Invoice Payment",
+   "options": "Sales Invoice Payment",
+   "print_hide": 1
+  },
+  {
+   "fieldname": "section_break_84",
+   "fieldtype": "Section Break"
+  },
+  {
+   "fieldname": "base_paid_amount",
+   "fieldtype": "Currency",
+   "label": "Paid Amount (Company Currency)",
+   "no_copy": 1,
+   "options": "Company:company:default_currency",
+   "print_hide": 1,
+   "read_only": 1
+  },
+  {
+   "fieldname": "column_break_86",
+   "fieldtype": "Column Break"
+  },
+  {
+   "depends_on": "eval: doc.is_pos || doc.redeem_loyalty_points",
+   "fieldname": "paid_amount",
+   "fieldtype": "Currency",
+   "label": "Paid Amount",
+   "no_copy": 1,
+   "oldfieldname": "paid_amount",
+   "oldfieldtype": "Currency",
+   "options": "currency",
+   "print_hide": 1,
+   "read_only": 1
+  },
+  {
+   "fieldname": "section_break_88",
+   "fieldtype": "Section Break"
+  },
+  {
+   "depends_on": "is_pos",
+   "fieldname": "base_change_amount",
+   "fieldtype": "Currency",
+   "label": "Base Change Amount (Company Currency)",
+   "no_copy": 1,
+   "options": "Company:company:default_currency",
+   "print_hide": 1,
+   "read_only": 1
+  },
+  {
+   "fieldname": "column_break_90",
+   "fieldtype": "Column Break"
+  },
+  {
+   "depends_on": "is_pos",
+   "fieldname": "change_amount",
+   "fieldtype": "Currency",
+   "label": "Change Amount",
+   "no_copy": 1,
+   "options": "currency",
+   "print_hide": 1
+  },
+  {
+   "depends_on": "is_pos",
+   "fieldname": "account_for_change_amount",
+   "fieldtype": "Link",
+   "label": "Account for Change Amount",
+   "options": "Account",
+   "print_hide": 1
+  },
+  {
+   "collapsible": 1,
+   "collapsible_depends_on": "write_off_amount",
+   "depends_on": "grand_total",
+   "fieldname": "column_break4",
+   "fieldtype": "Section Break",
+   "label": "Write Off",
+   "width": "50%"
+  },
+  {
+   "fieldname": "write_off_amount",
+   "fieldtype": "Currency",
+   "label": "Write Off Amount",
+   "no_copy": 1,
+   "options": "currency",
+   "print_hide": 1
+  },
+  {
+   "fieldname": "base_write_off_amount",
+   "fieldtype": "Currency",
+   "label": "Write Off Amount (Company Currency)",
+   "no_copy": 1,
+   "options": "Company:company:default_currency",
+   "print_hide": 1,
+   "read_only": 1
+  },
+  {
+   "default": "0",
+   "depends_on": "is_pos",
+   "fieldname": "write_off_outstanding_amount_automatically",
+   "fieldtype": "Check",
+   "label": "Write Off Outstanding Amount",
+   "print_hide": 1
+  },
+  {
+   "fieldname": "column_break_74",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "write_off_account",
+   "fieldtype": "Link",
+   "label": "Write Off Account",
+   "options": "Account",
+   "print_hide": 1
+  },
+  {
+   "fieldname": "write_off_cost_center",
+   "fieldtype": "Link",
+   "label": "Write Off Cost Center",
+   "options": "Cost Center",
+   "print_hide": 1
+  },
+  {
+   "collapsible": 1,
+   "collapsible_depends_on": "terms",
+   "fieldname": "terms_section_break",
+   "fieldtype": "Section Break",
+   "label": "Terms and Conditions",
+   "oldfieldtype": "Section Break"
+  },
+  {
+   "fieldname": "tc_name",
+   "fieldtype": "Link",
+   "label": "Terms",
+   "oldfieldname": "tc_name",
+   "oldfieldtype": "Link",
+   "options": "Terms and Conditions",
+   "print_hide": 1
+  },
+  {
+   "fieldname": "terms",
+   "fieldtype": "Text Editor",
+   "label": "Terms and Conditions Details",
+   "oldfieldname": "terms",
+   "oldfieldtype": "Text Editor"
+  },
+  {
+   "collapsible": 1,
+   "fieldname": "edit_printing_settings",
+   "fieldtype": "Section Break",
+   "label": "Printing Settings"
+  },
+  {
+   "allow_on_submit": 1,
+   "fieldname": "letter_head",
+   "fieldtype": "Link",
+   "label": "Letter Head",
+   "oldfieldname": "letter_head",
+   "oldfieldtype": "Select",
+   "options": "Letter Head",
+   "print_hide": 1
+  },
+  {
+   "allow_on_submit": 1,
+   "default": "0",
+   "fieldname": "group_same_items",
+   "fieldtype": "Check",
+   "label": "Group same items",
+   "print_hide": 1
+  },
+  {
+   "fieldname": "language",
+   "fieldtype": "Data",
+   "label": "Print Language",
+   "print_hide": 1,
+   "read_only": 1
+  },
+  {
+   "fieldname": "column_break_84",
+   "fieldtype": "Column Break"
+  },
+  {
+   "allow_on_submit": 1,
+   "fieldname": "select_print_heading",
+   "fieldtype": "Link",
+   "label": "Print Heading",
+   "no_copy": 1,
+   "oldfieldname": "select_print_heading",
+   "oldfieldtype": "Link",
+   "options": "Print Heading",
+   "print_hide": 1,
+   "report_hide": 1
+  },
+  {
+   "collapsible": 1,
+   "depends_on": "customer",
+   "fieldname": "more_information",
+   "fieldtype": "Section Break",
+   "label": "More Information"
+  },
+  {
+   "fieldname": "inter_company_invoice_reference",
+   "fieldtype": "Link",
+   "label": "Inter Company Invoice Reference",
+   "options": "Purchase Invoice",
+   "read_only": 1
+  },
+  {
+   "fieldname": "customer_group",
+   "fieldtype": "Link",
+   "hidden": 1,
+   "label": "Customer Group",
+   "options": "Customer Group",
+   "print_hide": 1
+  },
+  {
+   "fieldname": "campaign",
+   "fieldtype": "Link",
+   "label": "Campaign",
+   "oldfieldname": "campaign",
+   "oldfieldtype": "Link",
+   "options": "Campaign",
+   "print_hide": 1
+  },
+  {
+   "default": "0",
+   "fieldname": "is_discounted",
+   "fieldtype": "Check",
+   "label": "Is Discounted",
+   "no_copy": 1,
+   "read_only": 1
+  },
+  {
+   "fieldname": "col_break23",
+   "fieldtype": "Column Break",
+   "width": "50%"
+  },
+  {
+   "default": "Draft",
+   "fieldname": "status",
+   "fieldtype": "Select",
+   "in_standard_filter": 1,
+   "label": "Status",
+   "no_copy": 1,
+   "options": "\nDraft\nReturn\nCredit Note Issued\nConsolidated\nSubmitted\nPaid\nUnpaid\nUnpaid and Discounted\nOverdue and Discounted\nOverdue\nCancelled",
+   "print_hide": 1,
+   "read_only": 1
+  },
+  {
+   "fieldname": "source",
+   "fieldtype": "Link",
+   "label": "Source",
+   "oldfieldname": "source",
+   "oldfieldtype": "Select",
+   "options": "Lead Source",
+   "print_hide": 1
+  },
+  {
+   "collapsible": 1,
+   "fieldname": "more_info",
+   "fieldtype": "Section Break",
+   "label": "Accounting Details",
+   "oldfieldtype": "Section Break",
+   "options": "fa fa-file-text",
+   "print_hide": 1
+  },
+  {
+   "fieldname": "debit_to",
+   "fieldtype": "Link",
+   "label": "Debit To",
+   "oldfieldname": "debit_to",
+   "oldfieldtype": "Link",
+   "options": "Account",
+   "print_hide": 1,
+   "reqd": 1,
+   "search_index": 1
+  },
+  {
+   "fieldname": "party_account_currency",
+   "fieldtype": "Link",
+   "hidden": 1,
+   "label": "Party Account Currency",
+   "no_copy": 1,
+   "options": "Currency",
+   "print_hide": 1,
+   "read_only": 1
+  },
+  {
+   "default": "No",
+   "fieldname": "is_opening",
+   "fieldtype": "Select",
+   "label": "Is Opening Entry",
+   "oldfieldname": "is_opening",
+   "oldfieldtype": "Select",
+   "options": "No\nYes",
+   "print_hide": 1
+  },
+  {
+   "fieldname": "c_form_applicable",
+   "fieldtype": "Select",
+   "label": "C-Form Applicable",
+   "no_copy": 1,
+   "options": "No\nYes",
+   "print_hide": 1
+  },
+  {
+   "fieldname": "c_form_no",
+   "fieldtype": "Link",
+   "label": "C-Form No",
+   "no_copy": 1,
+   "options": "C-Form",
+   "print_hide": 1,
+   "read_only": 1
+  },
+  {
+   "fieldname": "column_break8",
+   "fieldtype": "Column Break",
+   "oldfieldtype": "Column Break",
+   "print_hide": 1
+  },
+  {
+   "fieldname": "remarks",
+   "fieldtype": "Small Text",
+   "label": "Remarks",
+   "no_copy": 1,
+   "oldfieldname": "remarks",
+   "oldfieldtype": "Text",
+   "print_hide": 1
+  },
+  {
+   "collapsible": 1,
+   "collapsible_depends_on": "sales_partner",
+   "fieldname": "sales_team_section_break",
+   "fieldtype": "Section Break",
+   "label": "Commission",
+   "oldfieldtype": "Section Break",
+   "options": "fa fa-group",
+   "print_hide": 1
+  },
+  {
+   "fieldname": "sales_partner",
+   "fieldtype": "Link",
+   "label": "Sales Partner",
+   "oldfieldname": "sales_partner",
+   "oldfieldtype": "Link",
+   "options": "Sales Partner",
+   "print_hide": 1
+  },
+  {
+   "fieldname": "column_break10",
+   "fieldtype": "Column Break",
+   "oldfieldtype": "Column Break",
+   "print_hide": 1,
+   "width": "50%"
+  },
+  {
+   "fieldname": "commission_rate",
+   "fieldtype": "Float",
+   "label": "Commission Rate (%)",
+   "oldfieldname": "commission_rate",
+   "oldfieldtype": "Currency",
+   "print_hide": 1
+  },
+  {
+   "fieldname": "total_commission",
+   "fieldtype": "Currency",
+   "label": "Total Commission",
+   "oldfieldname": "total_commission",
+   "oldfieldtype": "Currency",
+   "options": "Company:company:default_currency",
+   "print_hide": 1
+  },
+  {
+   "collapsible": 1,
+   "collapsible_depends_on": "sales_team",
+   "fieldname": "section_break2",
+   "fieldtype": "Section Break",
+   "label": "Sales Team",
+   "print_hide": 1
+  },
+  {
+   "allow_on_submit": 1,
+   "fieldname": "sales_team",
+   "fieldtype": "Table",
+   "label": "Sales Team1",
+   "oldfieldname": "sales_team",
+   "oldfieldtype": "Table",
+   "options": "Sales Team",
+   "print_hide": 1
+  },
+  {
+   "fieldname": "subscription_section",
+   "fieldtype": "Section Break",
+   "label": "Subscription Section"
+  },
+  {
+   "allow_on_submit": 1,
+   "fieldname": "from_date",
+   "fieldtype": "Date",
+   "label": "From Date",
+   "no_copy": 1,
+   "print_hide": 1
+  },
+  {
+   "allow_on_submit": 1,
+   "fieldname": "to_date",
+   "fieldtype": "Date",
+   "label": "To Date",
+   "no_copy": 1,
+   "print_hide": 1
+  },
+  {
+   "fieldname": "column_break_140",
+   "fieldtype": "Column Break"
+  },
+  {
+   "allow_on_submit": 1,
+   "fieldname": "auto_repeat",
+   "fieldtype": "Link",
+   "label": "Auto Repeat",
+   "no_copy": 1,
+   "options": "Auto Repeat",
+   "print_hide": 1,
+   "read_only": 1
+  },
+  {
+   "allow_on_submit": 1,
+   "depends_on": "eval: doc.auto_repeat",
+   "fieldname": "update_auto_repeat_reference",
+   "fieldtype": "Button",
+   "label": "Update Auto Repeat Reference"
+  },
+  {
+   "fieldname": "against_income_account",
+   "fieldtype": "Small Text",
+   "hidden": 1,
+   "label": "Against Income Account",
+   "no_copy": 1,
+   "oldfieldname": "against_income_account",
+   "oldfieldtype": "Small Text",
+   "print_hide": 1,
+   "report_hide": 1
+  },
+  {
+   "fieldname": "pos_total_qty",
+   "fieldtype": "Float",
+   "hidden": 1,
+   "label": "Total Qty",
+   "print_hide": 1,
+   "print_hide_if_no_value": 1,
+   "read_only": 1
+  },
+  {
+   "allow_on_submit": 1,
+   "fieldname": "consolidated_invoice",
+   "fieldtype": "Link",
+   "label": "Consolidated Sales Invoice",
+   "options": "Sales Invoice",
+   "read_only": 1
+  }
+ ],
+ "icon": "fa fa-file-text",
+ "is_submittable": 1,
+ "links": [],
+ "modified": "2020-05-29 15:08:39.337385",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "POS Invoice",
+ "name_case": "Title Case",
+ "owner": "Administrator",
+ "permissions": [
+  {
+   "amend": 1,
+   "cancel": 1,
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "Accounts Manager",
+   "share": 1,
+   "submit": 1,
+   "write": 1
+  },
+  {
+   "amend": 1,
+   "create": 1,
+   "email": 1,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "Accounts User",
+   "share": 1,
+   "submit": 1,
+   "write": 1
+  },
+  {
+   "permlevel": 1,
+   "read": 1,
+   "role": "Accounts Manager",
+   "write": 1
+  },
+  {
+   "permlevel": 1,
+   "read": 1,
+   "role": "All"
+  }
+ ],
+ "quick_entry": 1,
+ "search_fields": "posting_date, due_date, customer, base_grand_total, outstanding_amount",
+ "show_name_in_global_search": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "timeline_field": "customer",
+ "title_field": "title",
+ "track_changes": 1,
+ "track_seen": 1
+}
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/pos_invoice/pos_invoice.py b/erpnext/accounts/doctype/pos_invoice/pos_invoice.py
new file mode 100644
index 0000000..8680b71
--- /dev/null
+++ b/erpnext/accounts/doctype/pos_invoice/pos_invoice.py
@@ -0,0 +1,374 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe import _
+from frappe.model.document import Document
+from erpnext.controllers.selling_controller import SellingController
+from frappe.utils import cint, flt, add_months, today, date_diff, getdate, add_days, cstr, nowdate
+from erpnext.accounts.utils import get_account_currency
+from erpnext.accounts.party import get_party_account, get_due_date
+from erpnext.accounts.doctype.loyalty_program.loyalty_program import \
+	get_loyalty_program_details_with_points, validate_loyalty_points
+
+from erpnext.accounts.doctype.sales_invoice.sales_invoice import SalesInvoice, get_bank_cash_account, update_multi_mode_option
+from erpnext.stock.doctype.serial_no.serial_no import get_pos_reserved_serial_nos
+
+from six import iteritems
+
+class POSInvoice(SalesInvoice):
+	def __init__(self, *args, **kwargs):
+		super(POSInvoice, self).__init__(*args, **kwargs)
+	
+	def validate(self):
+		if not cint(self.is_pos):
+			frappe.throw(_("POS Invoice should have {} field checked.").format(frappe.bold("Include Payment")))
+
+		# run on validate method of selling controller
+		super(SalesInvoice, self).validate()
+		self.validate_auto_set_posting_time()
+		self.validate_pos_paid_amount()
+		self.validate_pos_return()
+		self.validate_uom_is_integer("stock_uom", "stock_qty")
+		self.validate_uom_is_integer("uom", "qty")
+		self.validate_debit_to_acc()
+		self.validate_write_off_account()
+		self.validate_change_amount()
+		self.validate_change_account()
+		self.validate_item_cost_centers()
+		self.validate_serialised_or_batched_item()
+		self.validate_stock_availablility()
+		self.validate_return_items()
+		self.set_status()
+		self.set_account_for_mode_of_payment()
+		self.validate_pos()
+		self.verify_payment_amount()
+		self.validate_loyalty_transaction()
+
+	def on_submit(self):
+		# create the loyalty point ledger entry if the customer is enrolled in any loyalty program
+		if self.loyalty_program:
+			self.make_loyalty_point_entry()
+		elif self.is_return and self.return_against and self.loyalty_program:
+			against_psi_doc = frappe.get_doc("POS Invoice", self.return_against)
+			against_psi_doc.delete_loyalty_point_entry()
+			against_psi_doc.make_loyalty_point_entry()
+		if self.redeem_loyalty_points and self.loyalty_points:
+			self.apply_loyalty_points()
+		self.set_status(update=True)
+	
+	def on_cancel(self):
+		# run on cancel method of selling controller
+		super(SalesInvoice, self).on_cancel()
+		if self.loyalty_program:
+			self.delete_loyalty_point_entry()
+		elif self.is_return and self.return_against and self.loyalty_program:
+			against_psi_doc = frappe.get_doc("POS Invoice", self.return_against)
+			against_psi_doc.delete_loyalty_point_entry()
+			against_psi_doc.make_loyalty_point_entry()
+		
+	def validate_stock_availablility(self):
+		allow_negative_stock = frappe.db.get_value('Stock Settings', None, 'allow_negative_stock')
+		
+		for d in self.get('items'):
+			if d.serial_no:
+				filters = {
+					"item_code": d.item_code,
+					"warehouse": d.warehouse,
+					"delivery_document_no": "",
+					"sales_invoice": ""
+				}
+				if d.batch_no:
+					filters["batch_no"] = d.batch_no
+				reserved_serial_nos, unreserved_serial_nos = get_pos_reserved_serial_nos(filters)
+				serial_nos = d.serial_no.split("\n")
+				serial_nos = ' '.join(serial_nos).split() # remove whitespaces
+				invalid_serial_nos = []
+				for s in serial_nos:
+					if s in reserved_serial_nos:
+						invalid_serial_nos.append(s)
+				
+				if len(invalid_serial_nos):
+					multiple_nos = 's' if len(invalid_serial_nos) > 1 else ''
+					frappe.throw(_("Row #{}: Serial No{}. {} has already been transacted into another POS Invoice. \
+						Please select valid serial no.".format(d.idx, multiple_nos, 
+						frappe.bold(', '.join(invalid_serial_nos)))), title=_("Not Available"))
+			else:
+				if allow_negative_stock:
+					return
+
+				available_stock = get_stock_availability(d.item_code, d.warehouse)
+				if not (flt(available_stock) > 0):
+					frappe.throw(_('Row #{}: Item Code: {} is not available under warehouse {}.'
+						.format(d.idx, frappe.bold(d.item_code), frappe.bold(d.warehouse))), title=_("Not Available"))
+				elif flt(available_stock) < flt(d.qty):
+					frappe.msgprint(_('Row #{}: Stock quantity not enough for Item Code: {} under warehouse {}. \
+						Available quantity {}.'.format(d.idx, frappe.bold(d.item_code), 
+						frappe.bold(d.warehouse), frappe.bold(d.qty))), title=_("Not Available"))
+	
+	def validate_serialised_or_batched_item(self):
+		for d in self.get("items"):
+			serialized = d.get("has_serial_no")
+			batched = d.get("has_batch_no")
+			no_serial_selected = not d.get("serial_no")
+			no_batch_selected = not d.get("batch_no")
+
+
+			if serialized and batched and (no_batch_selected or no_serial_selected):
+				frappe.throw(_('Row #{}: Please select a serial no and batch against item: {} or remove it to complete transaction.'
+						.format(d.idx, frappe.bold(d.item_code))), title=_("Invalid Item"))
+			if serialized and no_serial_selected:
+				frappe.throw(_('Row #{}: No serial number selected against item: {}. Please select one or remove it to complete transaction.'
+						.format(d.idx, frappe.bold(d.item_code))), title=_("Invalid Item"))
+			if batched and no_batch_selected:
+				frappe.throw(_('Row #{}: No batch selected against item: {}. Please select a batch or remove it to complete transaction.'
+						.format(d.idx, frappe.bold(d.item_code))), title=_("Invalid Item"))
+	
+	def validate_return_items(self):
+		if not self.get("is_return"): return
+
+		for d in self.get("items"):
+			if d.get("qty") > 0:
+				frappe.throw(_("Row #{}: You cannot add postive quantities in a return invoice. Please remove item {} to complete the return.")
+					.format(d.idx, frappe.bold(d.item_code)), title=_("Invalid Item"))
+
+	def validate_pos_paid_amount(self):
+		if len(self.payments) == 0 and self.is_pos:
+			frappe.throw(_("At least one mode of payment is required for POS invoice."))
+
+	def validate_change_account(self):
+		if frappe.db.get_value("Account", self.account_for_change_amount, "company") != self.company:
+			frappe.throw(_("The selected change account {} doesn't belongs to Company {}.").format(self.account_for_change_amount, self.company))
+
+	def validate_change_amount(self):
+		grand_total = flt(self.rounded_total) or flt(self.grand_total)
+		base_grand_total = flt(self.base_rounded_total) or flt(self.base_grand_total)
+		if not flt(self.change_amount) and grand_total < flt(self.paid_amount):
+			self.change_amount = flt(self.paid_amount - grand_total + flt(self.write_off_amount))
+			self.base_change_amount = flt(self.base_paid_amount - base_grand_total + flt(self.base_write_off_amount))
+
+		if flt(self.change_amount) and not self.account_for_change_amount:
+			msgprint(_("Please enter Account for Change Amount"), raise_exception=1)
+
+	def verify_payment_amount(self):
+		for entry in self.payments:
+			if not self.is_return and entry.amount < 0:
+				frappe.throw(_("Row #{0} (Payment Table): Amount must be positive").format(entry.idx))
+			if self.is_return and entry.amount > 0:
+				frappe.throw(_("Row #{0} (Payment Table): Amount must be negative").format(entry.idx))
+	
+	def validate_pos_return(self):
+		if self.is_pos and self.is_return:
+			total_amount_in_payments = 0
+			for payment in self.payments:
+				total_amount_in_payments += payment.amount
+			invoice_total = self.rounded_total or self.grand_total
+			if total_amount_in_payments < invoice_total:
+				frappe.throw(_("Total payments amount can't be greater than {}".format(-invoice_total)))
+	
+	def validate_loyalty_transaction(self):
+		if self.redeem_loyalty_points and (not self.loyalty_redemption_account or not self.loyalty_redemption_cost_center):
+			expense_account, cost_center = frappe.db.get_value('Loyalty Program', self.loyalty_program, ["expense_account", "cost_center"])
+			if not self.loyalty_redemption_account:
+				self.loyalty_redemption_account = expense_account 
+			if not self.loyalty_redemption_cost_center:
+				self.loyalty_redemption_cost_center = cost_center
+
+		if self.redeem_loyalty_points and self.loyalty_program and self.loyalty_points:
+			validate_loyalty_points(self, self.loyalty_points)
+
+	def set_status(self, update=False, status=None, update_modified=True):
+		if self.is_new():
+			if self.get('amended_from'):
+				self.status = 'Draft'
+			return
+
+		if not status:
+			if self.docstatus == 2:
+				status = "Cancelled"
+			elif self.docstatus == 1:
+				if self.consolidated_invoice:
+					self.status = "Consolidated"
+				elif flt(self.outstanding_amount) > 0 and getdate(self.due_date) < getdate(nowdate()) and self.is_discounted and self.get_discounting_status()=='Disbursed':
+					self.status = "Overdue and Discounted"
+				elif flt(self.outstanding_amount) > 0 and getdate(self.due_date) < getdate(nowdate()):
+					self.status = "Overdue"
+				elif flt(self.outstanding_amount) > 0 and getdate(self.due_date) >= getdate(nowdate()) and self.is_discounted and self.get_discounting_status()=='Disbursed':
+					self.status = "Unpaid and Discounted"
+				elif flt(self.outstanding_amount) > 0 and getdate(self.due_date) >= getdate(nowdate()):
+					self.status = "Unpaid"
+				elif flt(self.outstanding_amount) <= 0 and self.is_return == 0 and frappe.db.get_value('POS Invoice', {'is_return': 1, 'return_against': self.name, 'docstatus': 1}):
+					self.status = "Credit Note Issued"
+				elif self.is_return == 1:
+					self.status = "Return"
+				elif flt(self.outstanding_amount)<=0:
+					self.status = "Paid"
+				else:
+					self.status = "Submitted"
+			else:
+				self.status = "Draft"
+
+		if update:
+			self.db_set('status', self.status, update_modified = update_modified)
+	
+	def set_pos_fields(self, for_validate=False):
+		"""Set retail related fields from POS Profiles"""
+		from erpnext.stock.get_item_details import get_pos_profile_item_details, get_pos_profile
+		if not self.pos_profile:
+			pos_profile = get_pos_profile(self.company) or {}
+			self.pos_profile = pos_profile.get('name')
+
+		pos = {}
+		if self.pos_profile:
+			pos = frappe.get_doc('POS Profile', self.pos_profile)
+
+		if not self.get('payments') and not for_validate:
+			update_multi_mode_option(self, pos)
+
+		if not self.account_for_change_amount:
+			self.account_for_change_amount = frappe.get_cached_value('Company',  self.company,  'default_cash_account')
+
+		if pos:
+			if not for_validate:
+				self.tax_category = pos.get("tax_category")
+
+			if not for_validate and not self.customer:
+				self.customer = pos.customer
+
+			self.ignore_pricing_rule = pos.ignore_pricing_rule
+			if pos.get('account_for_change_amount'):
+				self.account_for_change_amount = pos.get('account_for_change_amount')
+			if pos.get('warehouse'):
+				self.set_warehouse = pos.get('warehouse')
+
+			for fieldname in ('naming_series', 'currency', 'letter_head', 'tc_name',
+				'company', 'select_print_heading', 'write_off_account', 'taxes_and_charges',
+				'write_off_cost_center', 'apply_discount_on', 'cost_center'):
+					if (not for_validate) or (for_validate and not self.get(fieldname)):
+						self.set(fieldname, pos.get(fieldname))
+
+			if pos.get("company_address"):
+				self.company_address = pos.get("company_address")
+
+			if self.customer:
+				customer_price_list, customer_group = frappe.db.get_value("Customer", self.customer, ['default_price_list', 'customer_group'])
+				customer_group_price_list = frappe.db.get_value("Customer Group", customer_group, 'default_price_list')
+				selling_price_list = customer_price_list or customer_group_price_list or pos.get('selling_price_list')
+			else:
+				selling_price_list = pos.get('selling_price_list')
+
+			if selling_price_list:
+				self.set('selling_price_list', selling_price_list)
+
+			if not for_validate:
+				self.update_stock = cint(pos.get("update_stock"))
+
+			# set pos values in items
+			for item in self.get("items"):
+				if item.get('item_code'):
+					profile_details = get_pos_profile_item_details(pos, frappe._dict(item.as_dict()), pos)
+					for fname, val in iteritems(profile_details):
+						if (not for_validate) or (for_validate and not item.get(fname)):
+							item.set(fname, val)
+
+			# fetch terms
+			if self.tc_name and not self.terms:
+				self.terms = frappe.db.get_value("Terms and Conditions", self.tc_name, "terms")
+
+			# fetch charges
+			if self.taxes_and_charges and not len(self.get("taxes")):
+				self.set_taxes()
+
+		return pos
+
+	def set_missing_values(self, for_validate=False):
+		pos = self.set_pos_fields(for_validate)
+
+		if not self.debit_to:
+			self.debit_to = get_party_account("Customer", self.customer, self.company)
+			self.party_account_currency = frappe.db.get_value("Account", self.debit_to, "account_currency", cache=True)
+		if not self.due_date and self.customer:
+			self.due_date = get_due_date(self.posting_date, "Customer", self.customer, self.company)
+
+		super(SalesInvoice, self).set_missing_values(for_validate)
+
+		print_format = pos.get("print_format") if pos else None
+		if not print_format and not cint(frappe.db.get_value('Print Format', 'POS Invoice', 'disabled')):
+			print_format = 'POS Invoice'
+
+		if pos:
+			return {
+				"print_format": print_format,
+				"allow_edit_rate": pos.get("allow_user_to_edit_rate"),
+				"allow_edit_discount": pos.get("allow_user_to_edit_discount"),
+				"campaign": pos.get("campaign"),
+				"allow_print_before_pay": pos.get("allow_print_before_pay")
+			}
+
+	def set_account_for_mode_of_payment(self):
+		self.payments = [d for d in self.payments if d.amount or d.base_amount or d.default]
+		for pay in self.payments:
+			if not pay.account:
+				pay.account = get_bank_cash_account(pay.mode_of_payment, self.company).get("account")
+
+@frappe.whitelist()
+def get_stock_availability(item_code, warehouse):
+	latest_sle = frappe.db.sql("""select qty_after_transaction 
+		from `tabStock Ledger Entry` 
+		where item_code = %s and warehouse = %s
+		order by posting_date desc, posting_time desc
+		limit 1""", (item_code, warehouse), as_dict=1)
+	
+	pos_sales_qty = frappe.db.sql("""select sum(p_item.qty) as qty
+		from `tabPOS Invoice` p, `tabPOS Invoice Item` p_item
+		where p.name = p_item.parent 
+		and p.consolidated_invoice is NULL 
+		and p.docstatus = 1
+		and p_item.docstatus = 1
+		and p_item.item_code = %s
+		and p_item.warehouse = %s
+		""", (item_code, warehouse), as_dict=1)
+	
+	sle_qty = latest_sle[0].qty_after_transaction or 0 if latest_sle else 0
+	pos_sales_qty = pos_sales_qty[0].qty or 0 if pos_sales_qty else 0
+	
+	if sle_qty and pos_sales_qty and sle_qty > pos_sales_qty:
+		return sle_qty - pos_sales_qty
+	else:
+		# when sle_qty is 0
+		# when sle_qty > 0 and pos_sales_qty is 0
+		return sle_qty
+
+@frappe.whitelist()
+def make_sales_return(source_name, target_doc=None):
+	from erpnext.controllers.sales_and_purchase_return import make_return_doc
+	return make_return_doc("POS Invoice", source_name, target_doc)
+
+@frappe.whitelist()
+def make_merge_log(invoices):
+	import json
+	from six import string_types
+
+	if isinstance(invoices, string_types):
+		invoices = json.loads(invoices)
+
+	if len(invoices) == 0:
+		frappe.throw(_('Atleast one invoice has to be selected.'))
+
+	merge_log = frappe.new_doc("POS Invoice Merge Log")
+	merge_log.posting_date = getdate(nowdate())
+	for inv in invoices:
+		inv_data = frappe.db.get_values("POS Invoice", inv.get('name'), 
+			["customer", "posting_date", "grand_total"], as_dict=1)[0]
+		merge_log.customer = inv_data.customer
+		merge_log.append("pos_invoices", {
+			'pos_invoice': inv.get('name'),
+			'customer': inv_data.customer,
+			'posting_date': inv_data.posting_date,
+			'grand_total': inv_data.grand_total 
+		})
+
+	if merge_log.get('pos_invoices'):
+		return merge_log.as_dict()
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/pos_invoice/pos_invoice_list.js b/erpnext/accounts/doctype/pos_invoice/pos_invoice_list.js
new file mode 100644
index 0000000..2dbf2a4
--- /dev/null
+++ b/erpnext/accounts/doctype/pos_invoice/pos_invoice_list.js
@@ -0,0 +1,42 @@
+// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
+// License: GNU General Public License v3. See license.txt
+
+// render
+frappe.listview_settings['POS Invoice'] = {
+	add_fields: ["customer", "customer_name", "base_grand_total", "outstanding_amount", "due_date", "company",
+		"currency", "is_return"],
+	get_indicator: function(doc) {
+		var status_color = {
+			"Draft": "red",
+			"Unpaid": "orange",
+			"Paid": "green",
+			"Submitted": "blue",
+			"Consolidated": "green",
+			"Return": "darkgrey",
+			"Unpaid and Discounted": "orange",
+			"Overdue and Discounted": "red",
+			"Overdue": "red"
+
+		};
+		return [__(doc.status), status_color[doc.status], "status,=,"+doc.status];
+	},
+	right_column: "grand_total",
+	onload: function(me) {
+		me.page.add_action_item('Make Merge Log', function() {
+			const invoices = me.get_checked_items();
+			frappe.call({
+				method: "erpnext.accounts.doctype.pos_invoice.pos_invoice.make_merge_log",
+				freeze: true,
+				args:{
+					"invoices": invoices
+				},
+				callback: function (r) {
+					if (r.message) {
+						var doc = frappe.model.sync(r.message)[0];
+						frappe.set_route("Form", doc.doctype, doc.name);
+					}
+				}
+			});
+		});
+	},
+};
diff --git a/erpnext/accounts/doctype/pos_invoice/test_pos_invoice.py b/erpnext/accounts/doctype/pos_invoice/test_pos_invoice.py
new file mode 100644
index 0000000..f295725
--- /dev/null
+++ b/erpnext/accounts/doctype/pos_invoice/test_pos_invoice.py
@@ -0,0 +1,324 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
+# See license.txt
+from __future__ import unicode_literals
+
+import frappe
+import unittest, copy, time
+from erpnext.accounts.doctype.pos_profile.test_pos_profile import make_pos_profile
+from erpnext.accounts.doctype.pos_invoice.pos_invoice import make_sales_return
+
+class TestPOSInvoice(unittest.TestCase):
+	def test_timestamp_change(self):
+		w = create_pos_invoice(do_not_save=1)
+		w.docstatus = 0
+		w.insert()
+
+		w2 = frappe.get_doc(w.doctype, w.name)
+
+		import time
+		time.sleep(1)
+		w.save()
+
+		import time
+		time.sleep(1)
+		self.assertRaises(frappe.TimestampMismatchError, w2.save)
+	
+	def test_change_naming_series(self):
+		inv = create_pos_invoice(do_not_submit=1)
+		inv.naming_series = 'TEST-'
+
+		self.assertRaises(frappe.CannotChangeConstantError, inv.save)
+	
+	def test_discount_and_inclusive_tax(self):
+		inv = create_pos_invoice(qty=100, rate=50, do_not_save=1)
+		inv.append("taxes", {
+			"charge_type": "On Net Total",
+			"account_head": "_Test Account Service Tax - _TC",
+			"cost_center": "_Test Cost Center - _TC",
+			"description": "Service Tax",
+			"rate": 14,
+			'included_in_print_rate': 1
+		})
+		inv.insert()
+
+		self.assertEqual(inv.net_total, 4385.96)
+		self.assertEqual(inv.grand_total, 5000)
+
+		inv.reload()
+
+		inv.discount_amount = 100
+		inv.apply_discount_on = 'Net Total'
+		inv.payment_schedule = []
+
+		inv.save()
+
+		self.assertEqual(inv.net_total, 4285.96)
+		self.assertEqual(inv.grand_total, 4885.99)
+
+		inv.reload()
+
+		inv.discount_amount = 100
+		inv.apply_discount_on = 'Grand Total'
+		inv.payment_schedule = []
+
+		inv.save()
+
+		self.assertEqual(inv.net_total, 4298.25)
+		self.assertEqual(inv.grand_total, 4900.00)
+	
+	def test_tax_calculation_with_multiple_items(self):
+		inv = create_pos_invoice(qty=84, rate=4.6, do_not_save=True)
+		item_row = inv.get("items")[0]
+		for qty in (54, 288, 144, 430):
+			item_row_copy = copy.deepcopy(item_row)
+			item_row_copy.qty = qty
+			inv.append("items", item_row_copy)
+
+		inv.append("taxes", {
+			"account_head": "_Test Account VAT - _TC",
+			"charge_type": "On Net Total",
+			"cost_center": "_Test Cost Center - _TC",
+			"description": "VAT",
+			"doctype": "Sales Taxes and Charges",
+			"rate": 19
+		})
+		inv.insert()
+
+		self.assertEqual(inv.net_total, 4600)
+
+		self.assertEqual(inv.get("taxes")[0].tax_amount, 874.0)
+		self.assertEqual(inv.get("taxes")[0].total, 5474.0)
+
+		self.assertEqual(inv.grand_total, 5474.0)
+
+	def test_tax_calculation_with_item_tax_template(self):
+		inv = create_pos_invoice(qty=84, rate=4.6, do_not_save=1)
+		item_row = inv.get("items")[0]
+
+		add_items = [
+			(54, '_Test Account Excise Duty @ 12'),
+			(288, '_Test Account Excise Duty @ 15'),
+			(144, '_Test Account Excise Duty @ 20'),
+			(430, '_Test Item Tax Template 1')
+		]
+		for qty, item_tax_template in add_items:
+			item_row_copy = copy.deepcopy(item_row)
+			item_row_copy.qty = qty
+			item_row_copy.item_tax_template = item_tax_template
+			inv.append("items", item_row_copy)
+
+		inv.append("taxes", {
+			"account_head": "_Test Account Excise Duty - _TC",
+			"charge_type": "On Net Total",
+			"cost_center": "_Test Cost Center - _TC",
+			"description": "Excise Duty",
+			"doctype": "Sales Taxes and Charges",
+			"rate": 11
+		})
+		inv.append("taxes", {
+			"account_head": "_Test Account Education Cess - _TC",
+			"charge_type": "On Net Total",
+			"cost_center": "_Test Cost Center - _TC",
+			"description": "Education Cess",
+			"doctype": "Sales Taxes and Charges",
+			"rate": 0
+		})
+		inv.append("taxes", {
+			"account_head": "_Test Account S&H Education Cess - _TC",
+			"charge_type": "On Net Total",
+			"cost_center": "_Test Cost Center - _TC",
+			"description": "S&H Education Cess",
+			"doctype": "Sales Taxes and Charges",
+			"rate": 3
+		})
+		inv.insert()
+
+		self.assertEqual(inv.net_total, 4600)
+
+		self.assertEqual(inv.get("taxes")[0].tax_amount, 502.41)
+		self.assertEqual(inv.get("taxes")[0].total, 5102.41)
+
+		self.assertEqual(inv.get("taxes")[1].tax_amount, 197.80)
+		self.assertEqual(inv.get("taxes")[1].total, 5300.21)
+
+		self.assertEqual(inv.get("taxes")[2].tax_amount, 375.36)
+		self.assertEqual(inv.get("taxes")[2].total, 5675.57)
+
+		self.assertEqual(inv.grand_total, 5675.57)
+		self.assertEqual(inv.rounding_adjustment, 0.43)
+		self.assertEqual(inv.rounded_total, 5676.0)
+	
+	def test_tax_calculation_with_multiple_items_and_discount(self):
+		inv = create_pos_invoice(qty=1, rate=75, do_not_save=True)
+		item_row = inv.get("items")[0]
+		for rate in (500, 200, 100, 50, 50):
+			item_row_copy = copy.deepcopy(item_row)
+			item_row_copy.price_list_rate = rate
+			item_row_copy.rate = rate
+			inv.append("items", item_row_copy)
+
+		inv.apply_discount_on = "Net Total"
+		inv.discount_amount = 75.0
+
+		inv.append("taxes", {
+			"account_head": "_Test Account VAT - _TC",
+			"charge_type": "On Net Total",
+			"cost_center": "_Test Cost Center - _TC",
+			"description": "VAT",
+			"doctype": "Sales Taxes and Charges",
+			"rate": 24
+		})
+		inv.insert()
+
+		self.assertEqual(inv.total, 975)
+		self.assertEqual(inv.net_total, 900)
+
+		self.assertEqual(inv.get("taxes")[0].tax_amount, 216.0)
+		self.assertEqual(inv.get("taxes")[0].total, 1116.0)
+
+		self.assertEqual(inv.grand_total, 1116.0)
+
+	def test_pos_returns_with_repayment(self):
+		pos = create_pos_invoice(qty = 10, do_not_save=True)
+
+		pos.append("payments", {'mode_of_payment': 'Bank Draft', 'account': '_Test Bank - _TC', 'amount': 500})
+		pos.append("payments", {'mode_of_payment': 'Cash', 'account': 'Cash - _TC', 'amount': 500})
+		pos.insert()
+		pos.submit()
+
+		pos_return = make_sales_return(pos.name)
+
+		pos_return.insert()
+		pos_return.submit()
+
+		self.assertEqual(pos_return.get('payments')[0].amount, -500)
+		self.assertEqual(pos_return.get('payments')[1].amount, -500)
+	
+	def test_pos_change_amount(self):
+		pos = create_pos_invoice(company= "_Test Company", debit_to="Debtors - _TC",
+			income_account = "Sales - _TC", expense_account = "Cost of Goods Sold - _TC", rate=105,
+			cost_center = "Main - _TC", do_not_save=True)
+
+		pos.append("payments", {'mode_of_payment': 'Bank Draft', 'account': '_Test Bank - _TC', 'amount': 50})
+		pos.append("payments", {'mode_of_payment': 'Cash', 'account': 'Cash - _TC', 'amount': 60})
+
+		pos.insert()
+		pos.submit()
+
+		self.assertEqual(pos.grand_total, 105.0)
+		self.assertEqual(pos.change_amount, 5.0)
+	
+	def test_without_payment(self):
+		inv = create_pos_invoice(do_not_save=1)
+		# Check that the invoice cannot be submitted without payments
+		inv.payments = []
+		self.assertRaises(frappe.ValidationError, inv.insert)
+	
+	def test_serialized_item_transaction(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
+
+		se = make_serialized_item(target_warehouse="_Test Warehouse - _TC")
+		serial_nos = get_serial_nos(se.get("items")[0].serial_no)
+
+		pos = create_pos_invoice(item=se.get("items")[0].item_code, rate=1000, do_not_save=1)
+		pos.get("items")[0].serial_no = serial_nos[0]
+		pos.append("payments", {'mode_of_payment': 'Bank Draft', 'account': '_Test Bank - _TC', 'amount': 1000})
+
+		pos.insert()
+		pos.submit()
+
+		pos2 = create_pos_invoice(item=se.get("items")[0].item_code, rate=1000, do_not_save=1)
+		pos2.get("items")[0].serial_no = serial_nos[0]
+		pos2.append("payments", {'mode_of_payment': 'Bank Draft', 'account': '_Test Bank - _TC', 'amount': 1000})
+		
+		self.assertRaises(frappe.ValidationError, pos2.insert)
+	
+	def test_loyalty_points(self):
+		from erpnext.accounts.doctype.loyalty_program.test_loyalty_program import create_records
+		from erpnext.accounts.doctype.loyalty_program.loyalty_program import get_loyalty_program_details_with_points
+
+		create_records()
+		frappe.db.set_value("Customer", "Test Loyalty Customer", "loyalty_program", "Test Single Loyalty")
+		before_lp_details = get_loyalty_program_details_with_points("Test Loyalty Customer", company="_Test Company", loyalty_program="Test Single Loyalty")
+
+		inv = create_pos_invoice(customer="Test Loyalty Customer", rate=10000)
+
+		lpe = frappe.get_doc('Loyalty Point Entry', {'invoice_type': 'POS Invoice', 'invoice': inv.name, 'customer': inv.customer})
+		after_lp_details = get_loyalty_program_details_with_points(inv.customer, company=inv.company, loyalty_program=inv.loyalty_program)
+
+		self.assertEqual(inv.get('loyalty_program'), "Test Single Loyalty")
+		self.assertEqual(lpe.loyalty_points, 10)
+		self.assertEqual(after_lp_details.loyalty_points, before_lp_details.loyalty_points + 10)
+
+		inv.cancel()
+		after_cancel_lp_details = get_loyalty_program_details_with_points(inv.customer, company=inv.company, loyalty_program=inv.loyalty_program)
+		self.assertEqual(after_cancel_lp_details.loyalty_points, before_lp_details.loyalty_points)
+	
+	def test_loyalty_points_redeemption(self):
+		from erpnext.accounts.doctype.loyalty_program.loyalty_program import get_loyalty_program_details_with_points
+		# add 10 loyalty points
+		create_pos_invoice(customer="Test Loyalty Customer", rate=10000)
+
+		before_lp_details = get_loyalty_program_details_with_points("Test Loyalty Customer", company="_Test Company", loyalty_program="Test Single Loyalty")
+		
+		inv = create_pos_invoice(customer="Test Loyalty Customer", rate=10000, do_not_save=1)
+		inv.redeem_loyalty_points = 1
+		inv.loyalty_points = before_lp_details.loyalty_points
+		inv.loyalty_amount = inv.loyalty_points * before_lp_details.conversion_factor
+		inv.append("payments", {'mode_of_payment': 'Cash', 'account': 'Cash - _TC', 'amount': 10000 - inv.loyalty_amount})
+		inv.paid_amount = 10000
+		inv.submit()
+
+		after_redeem_lp_details = get_loyalty_program_details_with_points(inv.customer, company=inv.company, loyalty_program=inv.loyalty_program)
+		self.assertEqual(after_redeem_lp_details.loyalty_points, 9)
+
+def create_pos_invoice(**args):
+	args = frappe._dict(args)
+	pos_profile = None
+	if not args.pos_profile:
+		pos_profile = make_pos_profile()
+		pos_profile.save()
+
+	pos_inv = frappe.new_doc("POS Invoice")
+	pos_inv.update_stock = 1
+	pos_inv.is_pos = 1
+	pos_inv.pos_profile = args.pos_profile or pos_profile.name
+
+	pos_inv.set_missing_values()
+
+	if args.posting_date:
+		pos_inv.set_posting_time = 1
+	pos_inv.posting_date = args.posting_date or frappe.utils.nowdate()
+
+	pos_inv.company = args.company or "_Test Company"
+	pos_inv.customer = args.customer or "_Test Customer"
+	pos_inv.debit_to = args.debit_to or "Debtors - _TC"
+	pos_inv.is_return = args.is_return
+	pos_inv.return_against = args.return_against
+	pos_inv.currency=args.currency or "INR"
+	pos_inv.conversion_rate = args.conversion_rate or 1
+	pos_inv.account_for_change_amount = "Cash - _TC"
+
+	pos_inv.append("items", {
+		"item_code": args.item or args.item_code or "_Test Item",
+		"warehouse": args.warehouse or "_Test Warehouse - _TC",
+		"qty": args.qty or 1,
+		"rate": args.rate if args.get("rate") is not None else 100,
+		"income_account": args.income_account or "Sales - _TC",
+		"expense_account": args.expense_account or "Cost of Goods Sold - _TC",
+		"cost_center": args.cost_center or "_Test Cost Center - _TC",
+		"serial_no": args.serial_no
+	})
+
+	if not args.do_not_save:
+		pos_inv.insert()
+		if not args.do_not_submit:
+			pos_inv.submit()
+		else:
+			pos_inv.payment_schedule = []
+	else:
+		pos_inv.payment_schedule = []
+
+	return pos_inv
\ No newline at end of file
diff --git a/erpnext/accounts/page/pos/__init__.py b/erpnext/accounts/doctype/pos_invoice_item/__init__.py
similarity index 100%
copy from erpnext/accounts/page/pos/__init__.py
copy to erpnext/accounts/doctype/pos_invoice_item/__init__.py
diff --git a/erpnext/accounts/doctype/pos_invoice_item/pos_invoice_item.json b/erpnext/accounts/doctype/pos_invoice_item/pos_invoice_item.json
new file mode 100644
index 0000000..2b6e7de
--- /dev/null
+++ b/erpnext/accounts/doctype/pos_invoice_item/pos_invoice_item.json
@@ -0,0 +1,805 @@
+{
+ "actions": [],
+ "autoname": "hash",
+ "creation": "2020-01-27 13:04:55.229516",
+ "doctype": "DocType",
+ "document_type": "Document",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "barcode",
+  "item_code",
+  "col_break1",
+  "item_name",
+  "customer_item_code",
+  "description_section",
+  "description",
+  "item_group",
+  "brand",
+  "image_section",
+  "image",
+  "image_view",
+  "quantity_and_rate",
+  "qty",
+  "stock_uom",
+  "col_break2",
+  "uom",
+  "conversion_factor",
+  "stock_qty",
+  "section_break_17",
+  "price_list_rate",
+  "base_price_list_rate",
+  "discount_and_margin",
+  "margin_type",
+  "margin_rate_or_amount",
+  "rate_with_margin",
+  "column_break_19",
+  "discount_percentage",
+  "discount_amount",
+  "base_rate_with_margin",
+  "section_break1",
+  "rate",
+  "amount",
+  "item_tax_template",
+  "col_break3",
+  "base_rate",
+  "base_amount",
+  "pricing_rules",
+  "is_free_item",
+  "section_break_21",
+  "net_rate",
+  "net_amount",
+  "column_break_24",
+  "base_net_rate",
+  "base_net_amount",
+  "drop_ship",
+  "delivered_by_supplier",
+  "accounting",
+  "income_account",
+  "is_fixed_asset",
+  "asset",
+  "finance_book",
+  "col_break4",
+  "expense_account",
+  "deferred_revenue",
+  "deferred_revenue_account",
+  "service_stop_date",
+  "enable_deferred_revenue",
+  "column_break_50",
+  "service_start_date",
+  "service_end_date",
+  "section_break_18",
+  "weight_per_unit",
+  "total_weight",
+  "column_break_21",
+  "weight_uom",
+  "warehouse_and_reference",
+  "warehouse",
+  "target_warehouse",
+  "quality_inspection",
+  "batch_no",
+  "col_break5",
+  "allow_zero_valuation_rate",
+  "serial_no",
+  "item_tax_rate",
+  "actual_batch_qty",
+  "actual_qty",
+  "edit_references",
+  "sales_order",
+  "so_detail",
+  "column_break_74",
+  "delivery_note",
+  "dn_detail",
+  "delivered_qty",
+  "accounting_dimensions_section",
+  "cost_center",
+  "dimension_col_break",
+  "project",
+  "section_break_54",
+  "page_break"
+ ],
+ "fields": [
+  {
+   "fieldname": "barcode",
+   "fieldtype": "Data",
+   "label": "Barcode",
+   "print_hide": 1
+  },
+  {
+   "bold": 1,
+   "columns": 4,
+   "fieldname": "item_code",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "label": "Item",
+   "oldfieldname": "item_code",
+   "oldfieldtype": "Link",
+   "options": "Item",
+   "search_index": 1
+  },
+  {
+   "fieldname": "col_break1",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "item_name",
+   "fieldtype": "Data",
+   "in_global_search": 1,
+   "label": "Item Name",
+   "oldfieldname": "item_name",
+   "oldfieldtype": "Data",
+   "print_hide": 1,
+   "reqd": 1
+  },
+  {
+   "fieldname": "customer_item_code",
+   "fieldtype": "Data",
+   "hidden": 1,
+   "label": "Customer's Item Code",
+   "print_hide": 1,
+   "read_only": 1
+  },
+  {
+   "collapsible": 1,
+   "fieldname": "description_section",
+   "fieldtype": "Section Break",
+   "label": "Description"
+  },
+  {
+   "fieldname": "description",
+   "fieldtype": "Text Editor",
+   "label": "Description",
+   "oldfieldname": "description",
+   "oldfieldtype": "Text",
+   "print_width": "200px",
+   "reqd": 1,
+   "width": "200px"
+  },
+  {
+   "fieldname": "item_group",
+   "fieldtype": "Link",
+   "hidden": 1,
+   "label": "Item Group",
+   "oldfieldname": "item_group",
+   "oldfieldtype": "Link",
+   "options": "Item Group",
+   "print_hide": 1,
+   "read_only": 1
+  },
+  {
+   "fieldname": "brand",
+   "fieldtype": "Data",
+   "hidden": 1,
+   "label": "Brand Name",
+   "oldfieldname": "brand",
+   "oldfieldtype": "Data",
+   "print_hide": 1
+  },
+  {
+   "collapsible": 1,
+   "fieldname": "image_section",
+   "fieldtype": "Section Break",
+   "label": "Image"
+  },
+  {
+   "fieldname": "image",
+   "fieldtype": "Attach",
+   "hidden": 1,
+   "label": "Image"
+  },
+  {
+   "fieldname": "image_view",
+   "fieldtype": "Image",
+   "label": "Image View",
+   "options": "image",
+   "print_hide": 1
+  },
+  {
+   "fieldname": "quantity_and_rate",
+   "fieldtype": "Section Break"
+  },
+  {
+   "bold": 1,
+   "columns": 2,
+   "fieldname": "qty",
+   "fieldtype": "Float",
+   "in_list_view": 1,
+   "label": "Quantity",
+   "oldfieldname": "qty",
+   "oldfieldtype": "Currency"
+  },
+  {
+   "fieldname": "stock_uom",
+   "fieldtype": "Link",
+   "label": "Stock UOM",
+   "options": "UOM",
+   "read_only": 1
+  },
+  {
+   "fieldname": "col_break2",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "uom",
+   "fieldtype": "Link",
+   "label": "UOM",
+   "options": "UOM",
+   "reqd": 1
+  },
+  {
+   "fieldname": "conversion_factor",
+   "fieldtype": "Float",
+   "label": "UOM Conversion Factor",
+   "print_hide": 1,
+   "reqd": 1
+  },
+  {
+   "fieldname": "stock_qty",
+   "fieldtype": "Float",
+   "label": "Qty as per Stock UOM",
+   "no_copy": 1,
+   "print_hide": 1,
+   "read_only": 1
+  },
+  {
+   "fieldname": "section_break_17",
+   "fieldtype": "Section Break"
+  },
+  {
+   "fieldname": "price_list_rate",
+   "fieldtype": "Currency",
+   "label": "Price List Rate",
+   "oldfieldname": "ref_rate",
+   "oldfieldtype": "Currency",
+   "options": "currency",
+   "print_hide": 1,
+   "read_only": 1
+  },
+  {
+   "fieldname": "base_price_list_rate",
+   "fieldtype": "Currency",
+   "label": "Price List Rate (Company Currency)",
+   "oldfieldname": "base_ref_rate",
+   "oldfieldtype": "Currency",
+   "options": "Company:company:default_currency",
+   "print_hide": 1,
+   "read_only": 1
+  },
+  {
+   "collapsible": 1,
+   "fieldname": "discount_and_margin",
+   "fieldtype": "Section Break",
+   "label": "Discount and Margin"
+  },
+  {
+   "depends_on": "price_list_rate",
+   "fieldname": "margin_type",
+   "fieldtype": "Select",
+   "label": "Margin Type",
+   "options": "\nPercentage\nAmount",
+   "print_hide": 1
+  },
+  {
+   "depends_on": "eval:doc.margin_type && doc.price_list_rate",
+   "fieldname": "margin_rate_or_amount",
+   "fieldtype": "Float",
+   "label": "Margin Rate or Amount",
+   "print_hide": 1
+  },
+  {
+   "depends_on": "eval:doc.margin_type && doc.price_list_rate && doc.margin_rate_or_amount",
+   "fieldname": "rate_with_margin",
+   "fieldtype": "Currency",
+   "label": "Rate With Margin",
+   "options": "currency",
+   "print_hide": 1,
+   "read_only": 1
+  },
+  {
+   "fieldname": "column_break_19",
+   "fieldtype": "Column Break"
+  },
+  {
+   "depends_on": "price_list_rate",
+   "fieldname": "discount_percentage",
+   "fieldtype": "Percent",
+   "label": "Discount (%) on Price List Rate with Margin",
+   "oldfieldname": "adj_rate",
+   "oldfieldtype": "Float",
+   "precision": "2",
+   "print_hide": 1
+  },
+  {
+   "depends_on": "price_list_rate",
+   "fieldname": "discount_amount",
+   "fieldtype": "Currency",
+   "label": "Discount Amount",
+   "options": "currency"
+  },
+  {
+   "depends_on": "eval:doc.margin_type && doc.price_list_rate && doc.margin_rate_or_amount",
+   "fieldname": "base_rate_with_margin",
+   "fieldtype": "Currency",
+   "label": "Rate With Margin (Company Currency)",
+   "options": "Company:company:default_currency",
+   "print_hide": 1,
+   "read_only": 1
+  },
+  {
+   "fieldname": "section_break1",
+   "fieldtype": "Section Break"
+  },
+  {
+   "bold": 1,
+   "columns": 2,
+   "fieldname": "rate",
+   "fieldtype": "Currency",
+   "in_list_view": 1,
+   "label": "Rate",
+   "oldfieldname": "export_rate",
+   "oldfieldtype": "Currency",
+   "options": "currency",
+   "reqd": 1
+  },
+  {
+   "columns": 2,
+   "fieldname": "amount",
+   "fieldtype": "Currency",
+   "in_list_view": 1,
+   "label": "Amount",
+   "oldfieldname": "export_amount",
+   "oldfieldtype": "Currency",
+   "options": "currency",
+   "read_only": 1,
+   "reqd": 1
+  },
+  {
+   "fieldname": "item_tax_template",
+   "fieldtype": "Link",
+   "label": "Item Tax Template",
+   "options": "Item Tax Template",
+   "print_hide": 1
+  },
+  {
+   "fieldname": "col_break3",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "base_rate",
+   "fieldtype": "Currency",
+   "label": "Rate (Company Currency)",
+   "oldfieldname": "basic_rate",
+   "oldfieldtype": "Currency",
+   "options": "Company:company:default_currency",
+   "print_hide": 1,
+   "read_only": 1,
+   "reqd": 1
+  },
+  {
+   "fieldname": "base_amount",
+   "fieldtype": "Currency",
+   "label": "Amount (Company Currency)",
+   "oldfieldname": "amount",
+   "oldfieldtype": "Currency",
+   "options": "Company:company:default_currency",
+   "print_hide": 1,
+   "read_only": 1,
+   "reqd": 1
+  },
+  {
+   "fieldname": "pricing_rules",
+   "fieldtype": "Small Text",
+   "hidden": 1,
+   "label": "Pricing Rules",
+   "print_hide": 1,
+   "read_only": 1
+  },
+  {
+   "default": "0",
+   "fieldname": "is_free_item",
+   "fieldtype": "Check",
+   "label": "Is Free Item",
+   "print_hide": 1,
+   "read_only": 1
+  },
+  {
+   "fieldname": "section_break_21",
+   "fieldtype": "Section Break"
+  },
+  {
+   "fieldname": "net_rate",
+   "fieldtype": "Currency",
+   "label": "Net Rate",
+   "options": "currency",
+   "print_hide": 1,
+   "read_only": 1
+  },
+  {
+   "fieldname": "net_amount",
+   "fieldtype": "Currency",
+   "label": "Net Amount",
+   "options": "currency",
+   "print_hide": 1,
+   "read_only": 1
+  },
+  {
+   "fieldname": "column_break_24",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "base_net_rate",
+   "fieldtype": "Currency",
+   "label": "Net Rate (Company Currency)",
+   "options": "Company:company:default_currency",
+   "print_hide": 1,
+   "read_only": 1
+  },
+  {
+   "fieldname": "base_net_amount",
+   "fieldtype": "Currency",
+   "label": "Net Amount (Company Currency)",
+   "options": "Company:company:default_currency",
+   "print_hide": 1,
+   "read_only": 1
+  },
+  {
+   "collapsible": 1,
+   "collapsible_depends_on": "eval:doc.delivered_by_supplier==1",
+   "fieldname": "drop_ship",
+   "fieldtype": "Section Break",
+   "label": "Drop Ship"
+  },
+  {
+   "default": "0",
+   "fieldname": "delivered_by_supplier",
+   "fieldtype": "Check",
+   "label": "Delivered By Supplier",
+   "print_hide": 1,
+   "read_only": 1
+  },
+  {
+   "collapsible": 1,
+   "fieldname": "accounting",
+   "fieldtype": "Section Break",
+   "label": "Accounting Details"
+  },
+  {
+   "fieldname": "income_account",
+   "fieldtype": "Link",
+   "label": "Income Account",
+   "oldfieldname": "income_account",
+   "oldfieldtype": "Link",
+   "options": "Account",
+   "print_hide": 1,
+   "print_width": "120px",
+   "reqd": 1,
+   "width": "120px"
+  },
+  {
+   "default": "0",
+   "fieldname": "is_fixed_asset",
+   "fieldtype": "Check",
+   "hidden": 1,
+   "label": "Is Fixed Asset",
+   "no_copy": 1,
+   "print_hide": 1,
+   "read_only": 1
+  },
+  {
+   "fieldname": "asset",
+   "fieldtype": "Link",
+   "label": "Asset",
+   "no_copy": 1,
+   "options": "Asset"
+  },
+  {
+   "depends_on": "asset",
+   "fieldname": "finance_book",
+   "fieldtype": "Link",
+   "label": "Finance Book",
+   "options": "Finance Book"
+  },
+  {
+   "fieldname": "col_break4",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "expense_account",
+   "fieldtype": "Link",
+   "label": "Expense Account",
+   "options": "Account",
+   "print_hide": 1,
+   "width": "120px"
+  },
+  {
+   "collapsible": 1,
+   "fieldname": "deferred_revenue",
+   "fieldtype": "Section Break",
+   "label": "Deferred Revenue"
+  },
+  {
+   "depends_on": "enable_deferred_revenue",
+   "fieldname": "deferred_revenue_account",
+   "fieldtype": "Link",
+   "label": "Deferred Revenue Account",
+   "options": "Account"
+  },
+  {
+   "allow_on_submit": 1,
+   "depends_on": "enable_deferred_revenue",
+   "fieldname": "service_stop_date",
+   "fieldtype": "Date",
+   "label": "Service Stop Date",
+   "no_copy": 1
+  },
+  {
+   "default": "0",
+   "fieldname": "enable_deferred_revenue",
+   "fieldtype": "Check",
+   "label": "Enable Deferred Revenue"
+  },
+  {
+   "fieldname": "column_break_50",
+   "fieldtype": "Column Break"
+  },
+  {
+   "depends_on": "enable_deferred_revenue",
+   "fieldname": "service_start_date",
+   "fieldtype": "Date",
+   "label": "Service Start Date",
+   "no_copy": 1
+  },
+  {
+   "depends_on": "enable_deferred_revenue",
+   "fieldname": "service_end_date",
+   "fieldtype": "Date",
+   "label": "Service End Date",
+   "no_copy": 1
+  },
+  {
+   "collapsible": 1,
+   "fieldname": "section_break_18",
+   "fieldtype": "Section Break",
+   "label": "Item Weight Details"
+  },
+  {
+   "fieldname": "weight_per_unit",
+   "fieldtype": "Float",
+   "label": "Weight Per Unit",
+   "print_hide": 1,
+   "read_only": 1
+  },
+  {
+   "fieldname": "total_weight",
+   "fieldtype": "Float",
+   "label": "Total Weight",
+   "print_hide": 1,
+   "read_only": 1
+  },
+  {
+   "fieldname": "column_break_21",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "weight_uom",
+   "fieldtype": "Link",
+   "label": "Weight UOM",
+   "options": "UOM",
+   "print_hide": 1,
+   "read_only": 1
+  },
+  {
+   "collapsible": 1,
+   "collapsible_depends_on": "eval:doc.serial_no || doc.batch_no",
+   "fieldname": "warehouse_and_reference",
+   "fieldtype": "Section Break",
+   "label": "Stock Details"
+  },
+  {
+   "fieldname": "warehouse",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "label": "Warehouse",
+   "oldfieldname": "warehouse",
+   "oldfieldtype": "Link",
+   "options": "Warehouse",
+   "print_hide": 1
+  },
+  {
+   "fieldname": "target_warehouse",
+   "fieldtype": "Link",
+   "hidden": 1,
+   "ignore_user_permissions": 1,
+   "label": "Customer Warehouse (Optional)",
+   "no_copy": 1,
+   "options": "Warehouse",
+   "print_hide": 1
+  },
+  {
+   "depends_on": "eval:!doc.__islocal",
+   "fieldname": "quality_inspection",
+   "fieldtype": "Link",
+   "label": "Quality Inspection",
+   "options": "Quality Inspection"
+  },
+  {
+   "fieldname": "batch_no",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "label": "Batch No",
+   "options": "Batch",
+   "print_hide": 1
+  },
+  {
+   "fieldname": "col_break5",
+   "fieldtype": "Column Break"
+  },
+  {
+   "default": "0",
+   "fieldname": "allow_zero_valuation_rate",
+   "fieldtype": "Check",
+   "label": "Allow Zero Valuation Rate",
+   "no_copy": 1,
+   "print_hide": 1
+  },
+  {
+   "fieldname": "serial_no",
+   "fieldtype": "Small Text",
+   "in_list_view": 1,
+   "label": "Serial No",
+   "oldfieldname": "serial_no",
+   "oldfieldtype": "Small Text"
+  },
+  {
+   "fieldname": "item_tax_rate",
+   "fieldtype": "Small Text",
+   "hidden": 1,
+   "label": "Item Tax Rate",
+   "oldfieldname": "item_tax_rate",
+   "oldfieldtype": "Small Text",
+   "print_hide": 1,
+   "read_only": 1
+  },
+  {
+   "allow_on_submit": 1,
+   "fieldname": "actual_batch_qty",
+   "fieldtype": "Float",
+   "label": "Available Batch Qty at Warehouse",
+   "no_copy": 1,
+   "print_hide": 1,
+   "print_width": "150px",
+   "read_only": 1,
+   "width": "150px"
+  },
+  {
+   "allow_on_submit": 1,
+   "fieldname": "actual_qty",
+   "fieldtype": "Float",
+   "label": "Available Qty at Warehouse",
+   "oldfieldname": "actual_qty",
+   "oldfieldtype": "Currency",
+   "print_hide": 1,
+   "read_only": 1
+  },
+  {
+   "collapsible": 1,
+   "fieldname": "edit_references",
+   "fieldtype": "Section Break",
+   "label": "References"
+  },
+  {
+   "fieldname": "sales_order",
+   "fieldtype": "Link",
+   "label": "Sales Order",
+   "no_copy": 1,
+   "oldfieldname": "sales_order",
+   "oldfieldtype": "Link",
+   "options": "Sales Order",
+   "print_hide": 1,
+   "read_only": 1,
+   "search_index": 1
+  },
+  {
+   "fieldname": "so_detail",
+   "fieldtype": "Data",
+   "hidden": 1,
+   "label": "Sales Order Item",
+   "no_copy": 1,
+   "oldfieldname": "so_detail",
+   "oldfieldtype": "Data",
+   "print_hide": 1,
+   "read_only": 1,
+   "search_index": 1
+  },
+  {
+   "fieldname": "column_break_74",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "delivery_note",
+   "fieldtype": "Link",
+   "label": "Delivery Note",
+   "no_copy": 1,
+   "oldfieldname": "delivery_note",
+   "oldfieldtype": "Link",
+   "options": "Delivery Note",
+   "print_hide": 1,
+   "read_only": 1,
+   "search_index": 1
+  },
+  {
+   "fieldname": "dn_detail",
+   "fieldtype": "Data",
+   "hidden": 1,
+   "label": "Delivery Note Item",
+   "no_copy": 1,
+   "oldfieldname": "dn_detail",
+   "oldfieldtype": "Data",
+   "print_hide": 1,
+   "read_only": 1,
+   "search_index": 1
+  },
+  {
+   "fieldname": "delivered_qty",
+   "fieldtype": "Float",
+   "label": "Delivered Qty",
+   "oldfieldname": "delivered_qty",
+   "oldfieldtype": "Currency",
+   "print_hide": 1,
+   "read_only": 1
+  },
+  {
+   "collapsible": 1,
+   "fieldname": "accounting_dimensions_section",
+   "fieldtype": "Section Break",
+   "label": "Accounting Dimensions"
+  },
+  {
+   "default": ":Company",
+   "fieldname": "cost_center",
+   "fieldtype": "Link",
+   "label": "Cost Center",
+   "oldfieldname": "cost_center",
+   "oldfieldtype": "Link",
+   "options": "Cost Center",
+   "print_hide": 1,
+   "print_width": "120px",
+   "reqd": 1,
+   "width": "120px"
+  },
+  {
+   "fieldname": "dimension_col_break",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "section_break_54",
+   "fieldtype": "Section Break"
+  },
+  {
+   "allow_on_submit": 1,
+   "default": "0",
+   "fieldname": "page_break",
+   "fieldtype": "Check",
+   "label": "Page Break",
+   "no_copy": 1,
+   "print_hide": 1,
+   "report_hide": 1
+  },
+  {
+   "fieldname": "project",
+   "fieldtype": "Link",
+   "label": "Project",
+   "options": "Project"
+  }
+ ],
+ "istable": 1,
+ "links": [],
+ "modified": "2020-07-22 13:40:34.418346",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "POS Invoice Item",
+ "owner": "Administrator",
+ "permissions": [],
+ "sort_field": "modified",
+ "sort_order": "DESC"
+}
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/pos_invoice_item/pos_invoice_item.py b/erpnext/accounts/doctype/pos_invoice_item/pos_invoice_item.py
new file mode 100644
index 0000000..92ce61b
--- /dev/null
+++ b/erpnext/accounts/doctype/pos_invoice_item/pos_invoice_item.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 POSInvoiceItem(Document):
+	pass
diff --git a/erpnext/accounts/page/pos/__init__.py b/erpnext/accounts/doctype/pos_invoice_merge_log/__init__.py
similarity index 100%
copy from erpnext/accounts/page/pos/__init__.py
copy to erpnext/accounts/doctype/pos_invoice_merge_log/__init__.py
diff --git a/erpnext/accounts/doctype/pos_invoice_merge_log/pos_invoice_merge_log.js b/erpnext/accounts/doctype/pos_invoice_merge_log/pos_invoice_merge_log.js
new file mode 100644
index 0000000..cd08efc
--- /dev/null
+++ b/erpnext/accounts/doctype/pos_invoice_merge_log/pos_invoice_merge_log.js
@@ -0,0 +1,16 @@
+// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+frappe.ui.form.on('POS Invoice Merge Log', {
+	setup: function(frm) {
+		frm.set_query("pos_invoice", "pos_invoices", doc => {
+			return{
+				filters: { 
+					'docstatus': 1,
+					'customer': doc.customer, 
+					'consolidated_invoice': '' 
+				}
+			}
+		});
+	}
+});
diff --git a/erpnext/accounts/doctype/pos_invoice_merge_log/pos_invoice_merge_log.json b/erpnext/accounts/doctype/pos_invoice_merge_log/pos_invoice_merge_log.json
new file mode 100644
index 0000000..8f97639
--- /dev/null
+++ b/erpnext/accounts/doctype/pos_invoice_merge_log/pos_invoice_merge_log.json
@@ -0,0 +1,147 @@
+{
+ "actions": [],
+ "creation": "2020-01-28 11:56:33.945372",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "posting_date",
+  "customer",
+  "section_break_3",
+  "pos_invoices",
+  "references_section",
+  "consolidated_invoice",
+  "column_break_7",
+  "consolidated_credit_note",
+  "amended_from"
+ ],
+ "fields": [
+  {
+   "fieldname": "posting_date",
+   "fieldtype": "Date",
+   "in_list_view": 1,
+   "label": "Posting Date",
+   "reqd": 1
+  },
+  {
+   "fieldname": "customer",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "label": "Customer",
+   "options": "Customer",
+   "reqd": 1
+  },
+  {
+   "fieldname": "section_break_3",
+   "fieldtype": "Section Break"
+  },
+  {
+   "fieldname": "pos_invoices",
+   "fieldtype": "Table",
+   "label": "POS Invoices",
+   "options": "POS Invoice Reference",
+   "reqd": 1
+  },
+  {
+   "collapsible": 1,
+   "fieldname": "references_section",
+   "fieldtype": "Section Break",
+   "label": "References"
+  },
+  {
+   "fieldname": "amended_from",
+   "fieldtype": "Link",
+   "label": "Amended From",
+   "no_copy": 1,
+   "options": "POS Invoice Merge Log",
+   "print_hide": 1,
+   "read_only": 1
+  },
+  {
+   "allow_on_submit": 1,
+   "fieldname": "consolidated_invoice",
+   "fieldtype": "Link",
+   "label": "Consolidated Sales Invoice",
+   "options": "Sales Invoice",
+   "read_only": 1
+  },
+  {
+   "fieldname": "column_break_7",
+   "fieldtype": "Column Break"
+  },
+  {
+   "allow_on_submit": 1,
+   "fieldname": "consolidated_credit_note",
+   "fieldtype": "Link",
+   "label": "Consolidated Credit Note",
+   "options": "Sales Invoice",
+   "read_only": 1
+  }
+ ],
+ "is_submittable": 1,
+ "links": [],
+ "modified": "2020-05-29 15:08:41.317100",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "POS Invoice Merge Log",
+ "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": "Sales Manager",
+   "share": 1,
+   "submit": 1,
+   "write": 1
+  },
+  {
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "export": 1,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "Sales User",
+   "share": 1,
+   "write": 1
+  },
+  {
+   "cancel": 1,
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "export": 1,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "Administrator",
+   "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/pos_invoice_merge_log/pos_invoice_merge_log.py b/erpnext/accounts/doctype/pos_invoice_merge_log/pos_invoice_merge_log.py
new file mode 100644
index 0000000..00dbad5
--- /dev/null
+++ b/erpnext/accounts/doctype/pos_invoice_merge_log/pos_invoice_merge_log.py
@@ -0,0 +1,180 @@
+# -*- 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 cint, flt, add_months, today, date_diff, getdate, add_days, cstr, nowdate
+from frappe.model.document import Document
+from frappe.model.mapper import map_doc
+from frappe.model import default_fields
+
+from six import iteritems
+
+class POSInvoiceMergeLog(Document):
+	def validate(self):
+		self.validate_customer()
+		self.validate_pos_invoice_status()
+
+	def validate_customer(self):
+		for d in self.pos_invoices:
+			if d.customer != self.customer:
+				frappe.throw(_("Row #{}: POS Invoice {} is not against customer {}").format(d.idx, d.pos_invoice, self.customer))
+
+	def validate_pos_invoice_status(self):
+		for d in self.pos_invoices:
+			status, docstatus = frappe.db.get_value('POS Invoice', d.pos_invoice, ['status', 'docstatus'])
+			if docstatus != 1:
+				frappe.throw(_("Row #{}: POS Invoice {} is not submitted yet").format(d.idx, d.pos_invoice))
+			if status in ['Consolidated']:
+				frappe.throw(_("Row #{}: POS Invoice {} has been {}").format(d.idx, d.pos_invoice, status))
+
+	def on_submit(self):
+		pos_invoice_docs = [frappe.get_doc("POS Invoice", d.pos_invoice) for d in self.pos_invoices]
+
+		returns = [d for d in pos_invoice_docs if d.get('is_return') == 1]
+		sales = [d for d in pos_invoice_docs if d.get('is_return') == 0]
+
+		sales_invoice = self.process_merging_into_sales_invoice(sales)
+		
+		if len(returns):
+			credit_note = self.process_merging_into_credit_note(returns)
+		else:
+			credit_note = ""
+
+		self.save() # save consolidated_sales_invoice & consolidated_credit_note ref in merge log
+
+		self.update_pos_invoices(sales_invoice, credit_note)
+
+	def process_merging_into_sales_invoice(self, data):
+		sales_invoice = self.get_new_sales_invoice()
+		
+		sales_invoice = self.merge_pos_invoice_into(sales_invoice, data)
+
+		sales_invoice.is_consolidated = 1
+		sales_invoice.save()
+		sales_invoice.submit()
+		self.consolidated_invoice = sales_invoice.name
+
+		return sales_invoice.name
+
+	def process_merging_into_credit_note(self, data):
+		credit_note = self.get_new_sales_invoice()
+		credit_note.is_return = 1
+
+		credit_note = self.merge_pos_invoice_into(credit_note, data)
+
+		credit_note.is_consolidated = 1
+		# TODO: return could be against multiple sales invoice which could also have been consolidated?
+		credit_note.return_against = self.consolidated_invoice
+		credit_note.save()
+		credit_note.submit()
+		self.consolidated_credit_note = credit_note.name
+
+		return credit_note.name
+	
+	def merge_pos_invoice_into(self, invoice, data):
+		items, payments, taxes = [], [], []
+		loyalty_amount_sum, loyalty_points_sum = 0, 0
+		for doc in data:
+			map_doc(doc, invoice, table_map={ "doctype": invoice.doctype })
+			
+			if doc.redeem_loyalty_points:
+				invoice.loyalty_redemption_account = doc.loyalty_redemption_account
+				invoice.loyalty_redemption_cost_center = doc.loyalty_redemption_cost_center
+				loyalty_points_sum += doc.loyalty_points
+				loyalty_amount_sum += doc.loyalty_amount
+			
+			for item in doc.get('items'):
+				items.append(item)
+			
+			for tax in doc.get('taxes'):
+				found = False
+				for t in taxes:
+					if t.account_head == tax.account_head and t.cost_center == tax.cost_center and t.rate == tax.rate:
+						t.tax_amount = flt(t.tax_amount) + flt(tax.tax_amount)
+						t.base_tax_amount = flt(t.base_tax_amount) + flt(tax.base_tax_amount)
+						found = True
+				if not found:
+					tax.charge_type = 'Actual'
+					taxes.append(tax)
+
+			for payment in doc.get('payments'):
+				found = False
+				for pay in payments:
+					if pay.account == payment.account and pay.mode_of_payment == payment.mode_of_payment:
+						pay.amount = flt(pay.amount) + flt(payment.amount)
+						pay.base_amount = flt(pay.base_amount) + flt(payment.base_amount)
+						found = True
+				if not found:
+					payments.append(payment)
+
+		if loyalty_points_sum:
+			invoice.redeem_loyalty_points = 1
+			invoice.loyalty_points = loyalty_points_sum
+			invoice.loyalty_amount = loyalty_amount_sum
+
+		invoice.set('items', items)
+		invoice.set('payments', payments)
+		invoice.set('taxes', taxes)
+
+		return invoice
+	
+	def get_new_sales_invoice(self):
+		sales_invoice = frappe.new_doc('Sales Invoice')
+		sales_invoice.customer = self.customer
+		sales_invoice.is_pos = 1
+		# date can be pos closing date?
+		sales_invoice.posting_date = getdate(nowdate())
+
+		return sales_invoice
+	
+	def update_pos_invoices(self, sales_invoice, credit_note):
+		for d in self.pos_invoices:
+			doc = frappe.get_doc('POS Invoice', d.pos_invoice)
+			if not doc.is_return:
+				doc.update({'consolidated_invoice': sales_invoice})
+			else:
+				doc.update({'consolidated_invoice': credit_note})
+			doc.set_status(update=True)
+			doc.save()
+
+def get_all_invoices():
+	filters = {
+		'consolidated_invoice': [ 'in', [ '', None ]],
+		'status': ['not in', ['Consolidated']],
+		'docstatus': 1
+	}
+	pos_invoices = frappe.db.get_all('POS Invoice', filters=filters,
+		fields=["name as pos_invoice", 'posting_date', 'grand_total', 'customer'])
+	
+	return pos_invoices
+
+def get_invoices_customer_map(pos_invoices):
+	# pos_invoice_customer_map = { 'Customer 1': [{}, {}, {}], 'Custoemr 2' : [{}] }
+	pos_invoice_customer_map = {}
+	for invoice in pos_invoices:
+		customer = invoice.get('customer')
+		pos_invoice_customer_map.setdefault(customer, [])
+		pos_invoice_customer_map[customer].append(invoice)
+	
+	return pos_invoice_customer_map
+
+def merge_pos_invoices(pos_invoices=[]):
+	if not pos_invoices:
+		pos_invoices = get_all_invoices()
+	
+	pos_invoice_map = get_invoices_customer_map(pos_invoices)
+	create_merge_logs(pos_invoice_map)
+
+def create_merge_logs(pos_invoice_customer_map):
+	for customer, invoices in iteritems(pos_invoice_customer_map):
+		merge_log = frappe.new_doc('POS Invoice Merge Log')
+		merge_log.posting_date = getdate(nowdate())
+		merge_log.customer = customer
+
+		merge_log.set('pos_invoices', invoices)
+		merge_log.save(ignore_permissions=True)
+		merge_log.submit()
+
diff --git a/erpnext/accounts/doctype/pos_invoice_merge_log/test_pos_invoice_merge_log.py b/erpnext/accounts/doctype/pos_invoice_merge_log/test_pos_invoice_merge_log.py
new file mode 100644
index 0000000..0f34272
--- /dev/null
+++ b/erpnext/accounts/doctype/pos_invoice_merge_log/test_pos_invoice_merge_log.py
@@ -0,0 +1,98 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
+# See license.txt
+from __future__ import unicode_literals
+
+import frappe
+import unittest
+from erpnext.accounts.doctype.pos_invoice.test_pos_invoice import create_pos_invoice
+from erpnext.accounts.doctype.pos_invoice.pos_invoice import make_sales_return
+from erpnext.accounts.doctype.pos_invoice_merge_log.pos_invoice_merge_log import merge_pos_invoices
+from erpnext.accounts.doctype.pos_closing_entry.test_pos_closing_entry import init_user_and_profile
+
+class TestPOSInvoiceMergeLog(unittest.TestCase):
+	def test_consolidated_invoice_creation(self):
+		frappe.db.sql("delete from `tabPOS Invoice`")
+
+		test_user, pos_profile = init_user_and_profile()
+
+		pos_inv = create_pos_invoice(rate=300, do_not_submit=1)
+		pos_inv.append('payments', {
+			'mode_of_payment': 'Cash', 'account': 'Cash - _TC', 'amount': 300
+		})
+		pos_inv.submit()
+
+		pos_inv2 = create_pos_invoice(rate=3200, do_not_submit=1)
+		pos_inv2.append('payments', {
+			'mode_of_payment': 'Cash', 'account': 'Cash - _TC', 'amount': 3200
+		})
+		pos_inv2.submit()
+
+		pos_inv3 = create_pos_invoice(customer="_Test Customer 2", rate=2300, do_not_submit=1)
+		pos_inv3.append('payments', {
+			'mode_of_payment': 'Cash', 'account': 'Cash - _TC', 'amount': 2300
+		})
+		pos_inv3.submit()
+
+		merge_pos_invoices()
+
+		pos_inv.load_from_db()
+		self.assertTrue(frappe.db.exists("Sales Invoice", pos_inv.consolidated_invoice))
+
+		pos_inv3.load_from_db()
+		self.assertTrue(frappe.db.exists("Sales Invoice", pos_inv3.consolidated_invoice))
+
+		self.assertFalse(pos_inv.consolidated_invoice == pos_inv3.consolidated_invoice)
+
+		frappe.set_user("Administrator")
+		frappe.db.sql("delete from `tabPOS Profile`")
+		frappe.db.sql("delete from `tabPOS Invoice`")
+	
+	def test_consolidated_credit_note_creation(self):
+		frappe.db.sql("delete from `tabPOS Invoice`")
+
+		test_user, pos_profile = init_user_and_profile()
+
+		pos_inv = create_pos_invoice(rate=300, do_not_submit=1)
+		pos_inv.append('payments', {
+			'mode_of_payment': 'Cash', 'account': 'Cash - _TC', 'amount': 300
+		})
+		pos_inv.submit()
+
+		pos_inv2 = create_pos_invoice(rate=3200, do_not_submit=1)
+		pos_inv2.append('payments', {
+			'mode_of_payment': 'Cash', 'account': 'Cash - _TC', 'amount': 3200
+		})
+		pos_inv2.submit()
+
+		pos_inv3 = create_pos_invoice(customer="_Test Customer 2", rate=2300, do_not_submit=1)
+		pos_inv3.append('payments', {
+			'mode_of_payment': 'Cash', 'account': 'Cash - _TC', 'amount': 2300
+		})
+		pos_inv3.submit()
+
+		pos_inv_cn = make_sales_return(pos_inv.name)
+		pos_inv_cn.set("payments", [])
+		pos_inv_cn.append('payments', {
+			'mode_of_payment': 'Cash', 'account': 'Cash - _TC', 'amount': -300
+		})
+		pos_inv_cn.paid_amount = -300
+		pos_inv_cn.submit()
+
+		merge_pos_invoices()
+
+		pos_inv.load_from_db()
+		self.assertTrue(frappe.db.exists("Sales Invoice", pos_inv.consolidated_invoice))
+
+		pos_inv3.load_from_db()
+		self.assertTrue(frappe.db.exists("Sales Invoice", pos_inv3.consolidated_invoice))
+
+		pos_inv_cn.load_from_db()
+		self.assertTrue(frappe.db.exists("Sales Invoice", pos_inv_cn.consolidated_invoice))
+		self.assertTrue(frappe.db.get_value("Sales Invoice", pos_inv_cn.consolidated_invoice, "is_return"))
+
+		frappe.set_user("Administrator")
+		frappe.db.sql("delete from `tabPOS Profile`")
+		frappe.db.sql("delete from `tabPOS Invoice`")
+
+
diff --git a/erpnext/accounts/page/pos/__init__.py b/erpnext/accounts/doctype/pos_invoice_reference/__init__.py
similarity index 100%
copy from erpnext/accounts/page/pos/__init__.py
copy to erpnext/accounts/doctype/pos_invoice_reference/__init__.py
diff --git a/erpnext/accounts/doctype/pos_invoice_reference/pos_invoice_reference.json b/erpnext/accounts/doctype/pos_invoice_reference/pos_invoice_reference.json
new file mode 100644
index 0000000..205c4ed
--- /dev/null
+++ b/erpnext/accounts/doctype/pos_invoice_reference/pos_invoice_reference.json
@@ -0,0 +1,65 @@
+{
+ "actions": [],
+ "creation": "2020-01-28 11:54:47.149392",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "pos_invoice",
+  "posting_date",
+  "column_break_3",
+  "customer",
+  "grand_total"
+ ],
+ "fields": [
+  {
+   "fieldname": "pos_invoice",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "label": "POS Invoice",
+   "options": "POS Invoice",
+   "reqd": 1
+  },
+  {
+   "fieldname": "column_break_3",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fetch_from": "pos_invoice.customer",
+   "fieldname": "customer",
+   "fieldtype": "Link",
+   "label": "Customer",
+   "options": "Customer",
+   "read_only": 1,
+   "reqd": 1
+  },
+  {
+   "fetch_from": "pos_invoice.posting_date",
+   "fieldname": "posting_date",
+   "fieldtype": "Date",
+   "in_list_view": 1,
+   "label": "Date",
+   "reqd": 1
+  },
+  {
+   "fetch_from": "pos_invoice.grand_total",
+   "fieldname": "grand_total",
+   "fieldtype": "Currency",
+   "in_list_view": 1,
+   "label": "Amount",
+   "reqd": 1
+  }
+ ],
+ "istable": 1,
+ "links": [],
+ "modified": "2020-05-29 15:08:42.194979",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "POS Invoice Reference",
+ "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/pos_invoice_reference/pos_invoice_reference.py b/erpnext/accounts/doctype/pos_invoice_reference/pos_invoice_reference.py
new file mode 100644
index 0000000..4c45265
--- /dev/null
+++ b/erpnext/accounts/doctype/pos_invoice_reference/pos_invoice_reference.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 POSInvoiceReference(Document):
+	pass
diff --git a/erpnext/accounts/page/pos/__init__.py b/erpnext/accounts/doctype/pos_opening_entry/__init__.py
similarity index 100%
copy from erpnext/accounts/page/pos/__init__.py
copy to erpnext/accounts/doctype/pos_opening_entry/__init__.py
diff --git a/erpnext/accounts/doctype/pos_opening_entry/pos_opening_entry.js b/erpnext/accounts/doctype/pos_opening_entry/pos_opening_entry.js
new file mode 100644
index 0000000..372e756
--- /dev/null
+++ b/erpnext/accounts/doctype/pos_opening_entry/pos_opening_entry.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('POS Opening Entry', {
+	setup(frm) {
+		if (frm.doc.docstatus == 0) {
+			frm.trigger('set_posting_date_read_only');
+			frm.set_value('period_start_date', frappe.datetime.now_datetime());
+			frm.set_value('user', frappe.session.user);
+		}
+
+		frm.set_query("user", function(doc) {
+			return {
+				query: "erpnext.accounts.doctype.pos_closing_entry.pos_closing_entry.get_cashiers",
+				filters: { 'parent': doc.pos_profile }
+			};
+		});
+	},
+
+	refresh(frm) {
+		// set default posting date / time
+		if(frm.doc.docstatus == 0) {
+			if(!frm.doc.posting_date) {
+				frm.set_value('posting_date', frappe.datetime.nowdate());
+			}
+			frm.trigger('set_posting_date_read_only');
+		}
+	},
+
+	set_posting_date_read_only(frm) {
+		if(frm.doc.docstatus == 0 && frm.doc.set_posting_date) {
+			frm.set_df_property('posting_date', 'read_only', 0);
+		} else {
+			frm.set_df_property('posting_date', 'read_only', 1);
+		}
+	},
+
+	set_posting_date(frm) {
+		frm.trigger('set_posting_date_read_only');
+	},
+
+	pos_profile: (frm) => {
+		if (frm.doc.pos_profile) {
+			frappe.db.get_doc("POS Profile", frm.doc.pos_profile)
+				.then(({ payments }) => {
+					if (payments.length) {
+						frm.doc.balance_details = [];
+						payments.forEach(({ mode_of_payment }) => {
+							frm.add_child("balance_details", { mode_of_payment });
+						})
+						frm.refresh_field("balance_details");
+					}
+				});
+		}
+	}
+});
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/pos_opening_entry/pos_opening_entry.json b/erpnext/accounts/doctype/pos_opening_entry/pos_opening_entry.json
new file mode 100644
index 0000000..de729ce
--- /dev/null
+++ b/erpnext/accounts/doctype/pos_opening_entry/pos_opening_entry.json
@@ -0,0 +1,185 @@
+{
+ "actions": [],
+ "autoname": "POS-OPE-.YYYY.-.#####",
+ "creation": "2020-03-05 16:58:53.083708",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "period_start_date",
+  "period_end_date",
+  "status",
+  "column_break_3",
+  "posting_date",
+  "set_posting_date",
+  "section_break_5",
+  "company",
+  "pos_profile",
+  "pos_closing_entry",
+  "column_break_7",
+  "user",
+  "opening_balance_details_section",
+  "balance_details",
+  "section_break_9",
+  "amended_from"
+ ],
+ "fields": [
+  {
+   "fieldname": "period_start_date",
+   "fieldtype": "Datetime",
+   "in_list_view": 1,
+   "label": "Period Start Date",
+   "reqd": 1
+  },
+  {
+   "fieldname": "period_end_date",
+   "fieldtype": "Date",
+   "in_list_view": 1,
+   "label": "Period End Date",
+   "read_only": 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": "section_break_5",
+   "fieldtype": "Section Break"
+  },
+  {
+   "fieldname": "company",
+   "fieldtype": "Link",
+   "label": "Company",
+   "options": "Company",
+   "reqd": 1
+  },
+  {
+   "fieldname": "pos_profile",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "label": "POS Profile",
+   "options": "POS Profile",
+   "reqd": 1
+  },
+  {
+   "fieldname": "column_break_7",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "user",
+   "fieldtype": "Link",
+   "label": "Cashier",
+   "options": "User",
+   "reqd": 1
+  },
+  {
+   "fieldname": "section_break_9",
+   "fieldtype": "Section Break",
+   "read_only": 1
+  },
+  {
+   "fieldname": "amended_from",
+   "fieldtype": "Link",
+   "label": "Amended From",
+   "no_copy": 1,
+   "options": "POS Opening Entry",
+   "print_hide": 1,
+   "read_only": 1
+  },
+  {
+   "default": "0",
+   "fieldname": "set_posting_date",
+   "fieldtype": "Check",
+   "label": "Set Posting Date"
+  },
+  {
+   "allow_on_submit": 1,
+   "default": "Draft",
+   "fieldname": "status",
+   "fieldtype": "Select",
+   "hidden": 1,
+   "label": "Status",
+   "options": "Draft\nOpen\nClosed\nCancelled",
+   "read_only": 1
+  },
+  {
+   "allow_on_submit": 1,
+   "fieldname": "pos_closing_entry",
+   "fieldtype": "Data",
+   "label": "POS Closing Entry",
+   "read_only": 1
+  },
+  {
+   "fieldname": "opening_balance_details_section",
+   "fieldtype": "Section Break"
+  },
+  {
+   "fieldname": "balance_details",
+   "fieldtype": "Table",
+   "label": "Opening Balance Details",
+   "options": "POS Opening Entry Detail",
+   "reqd": 1
+  }
+ ],
+ "is_submittable": 1,
+ "links": [],
+ "modified": "2020-05-29 15:08:40.955310",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "POS Opening Entry",
+ "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,
+   "email": 1,
+   "export": 1,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "Sales Manager",
+   "share": 1,
+   "submit": 1,
+   "write": 1
+  },
+  {
+   "cancel": 1,
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "export": 1,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "Administrator",
+   "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/pos_opening_entry/pos_opening_entry.py b/erpnext/accounts/doctype/pos_opening_entry/pos_opening_entry.py
new file mode 100644
index 0000000..15f23b6
--- /dev/null
+++ b/erpnext/accounts/doctype/pos_opening_entry/pos_opening_entry.py
@@ -0,0 +1,25 @@
+# -*- 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 cint
+from frappe.model.document import Document
+from erpnext.controllers.status_updater import StatusUpdater
+
+class POSOpeningEntry(StatusUpdater):
+	def validate(self):
+		self.validate_pos_profile_and_cashier()
+		self.set_status()
+
+	def validate_pos_profile_and_cashier(self):
+		if self.company != frappe.db.get_value("POS Profile", self.pos_profile, "company"):
+			frappe.throw(_("POS Profile {} does not belongs to company {}".format(self.pos_profile, self.company)))
+
+		if not cint(frappe.db.get_value("User", self.user, "enabled")):
+			frappe.throw(_("User {} has been disabled. Please select valid user/cashier".format(self.user)))
+
+	def on_submit(self):
+		self.set_status(update=True)
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/pos_opening_entry/pos_opening_entry_list.js b/erpnext/accounts/doctype/pos_opening_entry/pos_opening_entry_list.js
new file mode 100644
index 0000000..6c26ded
--- /dev/null
+++ b/erpnext/accounts/doctype/pos_opening_entry/pos_opening_entry_list.js
@@ -0,0 +1,16 @@
+// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
+// License: GNU General Public License v3. See license.txt
+
+// render
+frappe.listview_settings['POS Opening Entry'] = {
+	get_indicator: function(doc) {
+		var status_color = {
+			"Draft": "grey",
+			"Open": "orange",
+			"Closed": "green",
+			"Cancelled": "red"
+
+		};
+		return [__(doc.status), status_color[doc.status], "status,=,"+doc.status];
+	}
+};
diff --git a/erpnext/accounts/doctype/pos_opening_entry/test_pos_opening_entry.py b/erpnext/accounts/doctype/pos_opening_entry/test_pos_opening_entry.py
new file mode 100644
index 0000000..2e36391
--- /dev/null
+++ b/erpnext/accounts/doctype/pos_opening_entry/test_pos_opening_entry.py
@@ -0,0 +1,28 @@
+# -*- 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 TestPOSOpeningEntry(unittest.TestCase):
+	pass
+
+def create_opening_entry(pos_profile, user):
+	entry = frappe.new_doc("POS Opening Entry")
+	entry.pos_profile = pos_profile.name
+	entry.user = user
+	entry.company = pos_profile.company
+	entry.period_start_date = frappe.utils.get_datetime()
+
+	balance_details = [];
+	for d in pos_profile.payments:
+		balance_details.append(frappe._dict({
+			'mode_of_payment': d.mode_of_payment
+		}))
+	
+	entry.set("balance_details", balance_details)
+	entry.submit()
+	
+	return entry.as_dict()	
diff --git a/erpnext/accounts/page/pos/__init__.py b/erpnext/accounts/doctype/pos_opening_entry_detail/__init__.py
similarity index 100%
copy from erpnext/accounts/page/pos/__init__.py
copy to erpnext/accounts/doctype/pos_opening_entry_detail/__init__.py
diff --git a/erpnext/accounts/doctype/pos_opening_entry_detail/pos_opening_entry_detail.json b/erpnext/accounts/doctype/pos_opening_entry_detail/pos_opening_entry_detail.json
new file mode 100644
index 0000000..c23e3df
--- /dev/null
+++ b/erpnext/accounts/doctype/pos_opening_entry_detail/pos_opening_entry_detail.json
@@ -0,0 +1,42 @@
+{
+ "actions": [],
+ "creation": "2020-04-28 16:44:32.440794",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "mode_of_payment",
+  "opening_amount"
+ ],
+ "fields": [
+  {
+   "fieldname": "mode_of_payment",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "label": "Mode of Payment",
+   "options": "Mode of Payment",
+   "reqd": 1
+  },
+  {
+   "default": "0",
+   "fieldname": "opening_amount",
+   "fieldtype": "Currency",
+   "in_list_view": 1,
+   "label": "Opening Amount",
+   "options": "company:company_currency",
+   "reqd": 1
+  }
+ ],
+ "istable": 1,
+ "links": [],
+ "modified": "2020-05-29 15:08:41.949378",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "POS Opening Entry Detail",
+ "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/pos_opening_entry_detail/pos_opening_entry_detail.py b/erpnext/accounts/doctype/pos_opening_entry_detail/pos_opening_entry_detail.py
new file mode 100644
index 0000000..5557062
--- /dev/null
+++ b/erpnext/accounts/doctype/pos_opening_entry_detail/pos_opening_entry_detail.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 POSOpeningEntryDetail(Document):
+	pass
diff --git a/erpnext/accounts/page/pos/__init__.py b/erpnext/accounts/doctype/pos_payment_method/__init__.py
similarity index 100%
copy from erpnext/accounts/page/pos/__init__.py
copy to erpnext/accounts/doctype/pos_payment_method/__init__.py
diff --git a/erpnext/accounts/doctype/pos_payment_method/pos_payment_method.json b/erpnext/accounts/doctype/pos_payment_method/pos_payment_method.json
new file mode 100644
index 0000000..4d5e1eb
--- /dev/null
+++ b/erpnext/accounts/doctype/pos_payment_method/pos_payment_method.json
@@ -0,0 +1,40 @@
+{
+ "actions": [],
+ "creation": "2020-04-30 14:37:08.148707",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "default",
+  "mode_of_payment"
+ ],
+ "fields": [
+  {
+   "default": "0",
+   "depends_on": "eval:parent.doctype == 'POS Profile'",
+   "fieldname": "default",
+   "fieldtype": "Check",
+   "in_list_view": 1,
+   "label": "Default"
+  },
+  {
+   "fieldname": "mode_of_payment",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "label": "Mode of Payment",
+   "options": "Mode of Payment",
+   "reqd": 1
+  }
+ ],
+ "istable": 1,
+ "links": [],
+ "modified": "2020-05-29 15:08:41.704844",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "POS Payment Method",
+ "owner": "Administrator",
+ "permissions": [],
+ "quick_entry": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC"
+}
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/pos_payment_method/pos_payment_method.py b/erpnext/accounts/doctype/pos_payment_method/pos_payment_method.py
new file mode 100644
index 0000000..8a46d84
--- /dev/null
+++ b/erpnext/accounts/doctype/pos_payment_method/pos_payment_method.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 POSPaymentMethod(Document):
+	pass
diff --git a/erpnext/accounts/doctype/pos_profile/pos_profile.js b/erpnext/accounts/doctype/pos_profile/pos_profile.js
index 5e94118..ef431d7 100755
--- a/erpnext/accounts/doctype/pos_profile/pos_profile.js
+++ b/erpnext/accounts/doctype/pos_profile/pos_profile.js
@@ -28,7 +28,7 @@
 
 frappe.ui.form.on('POS Profile', {
 	setup: function(frm) {
-		frm.set_query("print_format_for_online", function() {
+		frm.set_query("print_format", function() {
 			return {
 				filters: [
 					['Print Format', 'doc_type', '=', 'Sales Invoice'],
@@ -49,12 +49,6 @@
 			return { filters: { doc_type: "Sales Invoice", print_format_type: "JS"} };
 		});
 
-		frappe.db.get_value('POS Settings', 'POS Settings', 'use_pos_in_offline_mode', (r) => {
-			const is_offline = r && cint(r.use_pos_in_offline_mode)
-			frm.toggle_display('offline_pos_section', is_offline);
-			frm.toggle_display('print_format_for_online', !is_offline);
-		});
-
 		frm.set_query('company_address', function(doc) {
 			if(!doc.company) {
 				frappe.throw(__('Please set Company'));
diff --git a/erpnext/accounts/doctype/pos_profile/pos_profile.json b/erpnext/accounts/doctype/pos_profile/pos_profile.json
index fba1bed..454c598 100644
--- a/erpnext/accounts/doctype/pos_profile/pos_profile.json
+++ b/erpnext/accounts/doctype/pos_profile/pos_profile.json
@@ -1,4 +1,5 @@
 {
+ "actions": [],
  "allow_rename": 1,
  "autoname": "Prompt",
  "creation": "2013-05-24 12:15:51",
@@ -11,17 +12,12 @@
   "customer",
   "company",
   "country",
-  "warehouse",
-  "campaign",
-  "company_address",
   "column_break_9",
   "update_stock",
   "ignore_pricing_rule",
-  "allow_delete",
-  "allow_user_to_edit_rate",
-  "allow_user_to_edit_discount",
-  "allow_print_before_pay",
-  "display_items_in_stock",
+  "warehouse",
+  "campaign",
+  "company_address",
   "section_break_15",
   "applicable_for_users",
   "section_break_11",
@@ -31,16 +27,11 @@
   "column_break_16",
   "customer_groups",
   "section_break_16",
-  "print_format_for_online",
+  "print_format",
   "letter_head",
   "column_break0",
   "tc_name",
   "select_print_heading",
-  "offline_pos_section",
-  "territory",
-  "column_break_31",
-  "print_format",
-  "customer_group",
   "section_break_19",
   "selling_price_list",
   "currency",
@@ -105,15 +96,6 @@
    "label": "Country"
   },
   {
-   "depends_on": "update_stock",
-   "fieldname": "warehouse",
-   "fieldtype": "Link",
-   "label": "Warehouse",
-   "oldfieldname": "warehouse",
-   "oldfieldtype": "Link",
-   "options": "Warehouse"
-  },
-  {
    "fieldname": "campaign",
    "fieldtype": "Link",
    "label": "Campaign",
@@ -130,48 +112,6 @@
    "fieldtype": "Column Break"
   },
   {
-   "default": "1",
-   "fieldname": "update_stock",
-   "fieldtype": "Check",
-   "label": "Update Stock"
-  },
-  {
-   "default": "0",
-   "fieldname": "ignore_pricing_rule",
-   "fieldtype": "Check",
-   "label": "Ignore Pricing Rule"
-  },
-  {
-   "default": "0",
-   "fieldname": "allow_delete",
-   "fieldtype": "Check",
-   "label": "Allow Delete"
-  },
-  {
-   "default": "0",
-   "fieldname": "allow_user_to_edit_rate",
-   "fieldtype": "Check",
-   "label": "Allow user to edit Rate"
-  },
-  {
-   "default": "0",
-   "fieldname": "allow_user_to_edit_discount",
-   "fieldtype": "Check",
-   "label": "Allow user to edit Discount"
-  },
-  {
-   "default": "0",
-   "fieldname": "allow_print_before_pay",
-   "fieldtype": "Check",
-   "label": "Allow Print Before Pay"
-  },
-  {
-   "default": "0",
-   "fieldname": "display_items_in_stock",
-   "fieldtype": "Check",
-   "label": "Display Items In Stock"
-  },
-  {
    "fieldname": "section_break_15",
    "fieldtype": "Section Break",
    "label": "Applicable for Users"
@@ -185,13 +125,13 @@
   {
    "fieldname": "section_break_11",
    "fieldtype": "Section Break",
-   "label": "Mode of Payment"
+   "label": "Payment Methods"
   },
   {
    "fieldname": "payments",
    "fieldtype": "Table",
-   "label": "Sales Invoice Payment",
-   "options": "Sales Invoice Payment"
+   "options": "POS Payment Method",
+   "reqd": 1
   },
   {
    "fieldname": "section_break_14",
@@ -221,12 +161,6 @@
    "label": "Print Settings"
   },
   {
-   "fieldname": "print_format_for_online",
-   "fieldtype": "Link",
-   "label": "Print Format for Online",
-   "options": "Print Format"
-  },
-  {
    "allow_on_submit": 1,
    "fieldname": "letter_head",
    "fieldtype": "Link",
@@ -259,39 +193,6 @@
    "options": "Print Heading"
   },
   {
-   "fieldname": "offline_pos_section",
-   "fieldtype": "Section Break",
-   "label": "Offline POS Settings"
-  },
-  {
-   "fieldname": "territory",
-   "fieldtype": "Link",
-   "in_list_view": 1,
-   "label": "Territory",
-   "oldfieldname": "territory",
-   "oldfieldtype": "Link",
-   "options": "Territory",
-   "reqd": 1
-  },
-  {
-   "fieldname": "column_break_31",
-   "fieldtype": "Column Break"
-  },
-  {
-   "default": "Point of Sale",
-   "fieldname": "print_format",
-   "fieldtype": "Link",
-   "label": "Print Format",
-   "options": "Print Format"
-  },
-  {
-   "fieldname": "customer_group",
-   "fieldtype": "Link",
-   "label": "Customer Group",
-   "options": "Customer Group",
-   "reqd": 1
-  },
-  {
    "fieldname": "section_break_19",
    "fieldtype": "Section Break",
    "label": "Accounting"
@@ -381,19 +282,48 @@
    "label": "Accounting Dimensions"
   },
   {
-   "fieldname": "dimension_col_break",
-   "fieldtype": "Column Break"
-  },
-  {
    "fieldname": "tax_category",
    "fieldtype": "Link",
    "label": "Tax Category",
    "options": "Tax Category"
+  },
+  {
+   "fieldname": "dimension_col_break",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "print_format",
+   "fieldtype": "Link",
+   "label": "Print Format",
+   "options": "Print Format"
+  },
+  {
+   "depends_on": "update_stock",
+   "fieldname": "warehouse",
+   "fieldtype": "Link",
+   "label": "Warehouse",
+   "oldfieldname": "warehouse",
+   "oldfieldtype": "Link",
+   "options": "Warehouse",
+   "reqd": 1
+  },
+  {
+   "default": "0",
+   "fieldname": "update_stock",
+   "fieldtype": "Check",
+   "label": "Update Stock"
+  },
+  {
+   "default": "0",
+   "fieldname": "ignore_pricing_rule",
+   "fieldtype": "Check",
+   "label": "Ignore Pricing Rule"
   }
  ],
  "icon": "icon-cog",
  "idx": 1,
- "modified": "2020-01-24 15:52:03.797701",
+ "links": [],
+ "modified": "2020-06-29 12:20:30.977272",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "POS Profile",
diff --git a/erpnext/accounts/doctype/pos_profile/pos_profile.py b/erpnext/accounts/doctype/pos_profile/pos_profile.py
index 4f17e9f..8655b4b 100644
--- a/erpnext/accounts/doctype/pos_profile/pos_profile.py
+++ b/erpnext/accounts/doctype/pos_profile/pos_profile.py
@@ -5,8 +5,6 @@
 import frappe
 from frappe import msgprint, _
 from frappe.utils import cint, now
-from erpnext.accounts.doctype.sales_invoice.pos import get_child_nodes
-from erpnext.accounts.doctype.sales_invoice.sales_invoice import set_account_for_mode_of_payment
 from six import iteritems
 from frappe.model.document import Document
 
@@ -16,7 +14,6 @@
 		self.validate_all_link_fields()
 		self.validate_duplicate_groups()
 		self.check_default_payment()
-		self.validate_customer_territory_group()
 
 	def validate_default_profile(self):
 		for row in self.applicable_for_users:
@@ -64,19 +61,6 @@
 			if len(default_mode_of_payment) > 1:
 				frappe.throw(_("Multiple default mode of payment is not allowed"))
 
-	def validate_customer_territory_group(self):
-		if not frappe.db.get_single_value('POS Settings', 'use_pos_in_offline_mode'):
-			return
-
-		if not self.territory:
-			frappe.throw(_("Territory is Required in POS Profile"), title="Mandatory Field")
-
-		if not self.customer_group:
-			frappe.throw(_("Customer Group is Required in POS Profile"), title="Mandatory Field")
-
-	def before_save(self):
-		set_account_for_mode_of_payment(self)
-
 	def on_update(self):
 		self.set_defaults()
 
@@ -111,10 +95,16 @@
 
 	return list(set(item_groups))
 
+def get_child_nodes(group_type, root):
+	lft, rgt = frappe.db.get_value(group_type, root, ["lft", "rgt"])
+	return frappe.db.sql(""" Select name, lft, rgt from `tab{tab}` where
+			lft >= {lft} and rgt <= {rgt} order by lft""".format(tab=group_type, lft=lft, rgt=rgt), as_dict=1)
+
 @frappe.whitelist()
 def get_series():
-	return frappe.get_meta("Sales Invoice").get_field("naming_series").options or ""
+	return frappe.get_meta("POS Invoice").get_field("naming_series").options or "s"
 
+@frappe.whitelist()
 def pos_profile_query(doctype, txt, searchfield, start, page_len, filters):
 	user = frappe.session['user']
 	company = filters.get('company') or frappe.defaults.get_user_default('company')
diff --git a/erpnext/accounts/doctype/pos_profile/pos_profile_dashboard.py b/erpnext/accounts/doctype/pos_profile/pos_profile_dashboard.py
index e28bf73..2e4632a 100644
--- a/erpnext/accounts/doctype/pos_profile/pos_profile_dashboard.py
+++ b/erpnext/accounts/doctype/pos_profile/pos_profile_dashboard.py
@@ -8,7 +8,7 @@
 		'fieldname': 'pos_profile',
 		'transactions': [
 			{
-				'items': ['Sales Invoice', 'POS Closing Voucher']
+				'items': ['Sales Invoice', 'POS Closing Entry', 'POS Opening Entry']
 			}
 		]
 	}
diff --git a/erpnext/accounts/doctype/pos_profile/test_pos_profile.py b/erpnext/accounts/doctype/pos_profile/test_pos_profile.py
index 64d347d..8a4050c 100644
--- a/erpnext/accounts/doctype/pos_profile/test_pos_profile.py
+++ b/erpnext/accounts/doctype/pos_profile/test_pos_profile.py
@@ -6,7 +6,7 @@
 import frappe
 import unittest
 from erpnext.stock.get_item_details import get_pos_profile
-from erpnext.accounts.doctype.sales_invoice.pos import get_items_list, get_customers_list
+from erpnext.accounts.doctype.pos_profile.pos_profile import get_child_nodes
 
 class TestPOSProfile(unittest.TestCase):
 	def test_pos_profile(self):
@@ -29,6 +29,44 @@
 
 		frappe.db.sql("delete from `tabPOS Profile`")
 
+def get_customers_list(pos_profile={}):
+	cond = "1=1"
+	customer_groups = []
+	if pos_profile.get('customer_groups'):
+		# Get customers based on the customer groups defined in the POS profile
+		for d in pos_profile.get('customer_groups'):
+			customer_groups.extend([d.get('name') for d in get_child_nodes('Customer Group', d.get('customer_group'))])
+		cond = "customer_group in (%s)" % (', '.join(['%s'] * len(customer_groups)))
+
+	return frappe.db.sql(""" select name, customer_name, customer_group,
+		territory, customer_pos_id from tabCustomer where disabled = 0
+		and {cond}""".format(cond=cond), tuple(customer_groups), as_dict=1) or {}
+
+def get_items_list(pos_profile, company):
+	cond = ""
+	args_list = []
+	if pos_profile.get('item_groups'):
+		# Get items based on the item groups defined in the POS profile
+		for d in pos_profile.get('item_groups'):
+			args_list.extend([d.name for d in get_child_nodes('Item Group', d.item_group)])
+		if args_list:
+			cond = "and i.item_group in (%s)" % (', '.join(['%s'] * len(args_list)))
+
+	return frappe.db.sql("""
+		select
+			i.name, i.item_code, i.item_name, i.description, i.item_group, i.has_batch_no,
+			i.has_serial_no, i.is_stock_item, i.brand, i.stock_uom, i.image,
+			id.expense_account, id.selling_cost_center, id.default_warehouse,
+			i.sales_uom, c.conversion_factor
+		from
+			`tabItem` i
+		left join `tabItem Default` id on id.parent = i.name and id.company = %s
+		left join `tabUOM Conversion Detail` c on i.name = c.parent and i.sales_uom = c.uom
+		where
+			i.disabled = 0 and i.has_variants = 0 and i.is_sales_item = 1 and i.is_fixed_asset = 0
+			{cond}
+		""".format(cond=cond), tuple([company] + args_list), as_dict=1)
+
 def make_pos_profile(**args):
 	frappe.db.sql("delete from `tabPOS Profile`")
 
@@ -50,6 +88,12 @@
 		"write_off_account":  args.write_off_account or "_Test Write Off - _TC",
 		"write_off_cost_center":  args.write_off_cost_center or "_Test Write Off Cost Center - _TC"
 	})
+	
+	payments = [{
+		'mode_of_payment': 'Cash',
+		'default': 1
+	}]
+	pos_profile.set("payments", payments)
 
 	if not frappe.db.exists("POS Profile", args.name or "_Test POS Profile"):
 		pos_profile.insert()
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 59a673e..c8f3f5e 100644
--- a/erpnext/accounts/doctype/pos_profile_user/pos_profile_user.json
+++ b/erpnext/accounts/doctype/pos_profile_user/pos_profile_user.json
@@ -26,7 +26,7 @@
  ],
  "istable": 1,
  "links": [],
- "modified": "2020-05-01 09:46:47.599173",
+ "modified": "2020-05-13 23:57:33.627305",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "POS Profile User",
diff --git a/erpnext/accounts/doctype/pos_settings/pos_settings.js b/erpnext/accounts/doctype/pos_settings/pos_settings.js
index f5b681b..504941d 100644
--- a/erpnext/accounts/doctype/pos_settings/pos_settings.js
+++ b/erpnext/accounts/doctype/pos_settings/pos_settings.js
@@ -6,27 +6,19 @@
 		frm.trigger("get_invoice_fields");
 	},
 
-	use_pos_in_offline_mode: function(frm) {
-		frm.trigger("get_invoice_fields");
-	},
-
 	get_invoice_fields: function(frm) {
-		if (!frm.doc.use_pos_in_offline_mode) {
-			frappe.model.with_doctype("Sales Invoice", () => {
-				var fields = $.map(frappe.get_doc("DocType", "Sales Invoice").fields, function(d) {
-					if (frappe.model.no_value_type.indexOf(d.fieldtype) === -1 ||
-						d.fieldtype === 'Table') {
-						return { label: d.label + ' (' + d.fieldtype + ')', value: d.fieldname };
-					} else {
-						return null;
-					}
-				});
-
-				frappe.meta.get_docfield("POS Field", "fieldname", frm.doc.name).options = [""].concat(fields);
+		frappe.model.with_doctype("Sales Invoice", () => {
+			var fields = $.map(frappe.get_doc("DocType", "Sales Invoice").fields, function(d) {
+				if (frappe.model.no_value_type.indexOf(d.fieldtype) === -1 ||
+					d.fieldtype === 'Table') {
+					return { label: d.label + ' (' + d.fieldtype + ')', value: d.fieldname };
+				} else {
+					return null;
+				}
 			});
-		} else {
-			frappe.meta.get_docfield("POS Field", "fieldname", frm.doc.name).options = [""];
-		}
+
+			frappe.meta.get_docfield("POS Field", "fieldname", frm.doc.name).options = [""].concat(fields);
+		});
 	}
 });
 
diff --git a/erpnext/accounts/doctype/pos_settings/pos_settings.json b/erpnext/accounts/doctype/pos_settings/pos_settings.json
index 1d55880..3539588 100644
--- a/erpnext/accounts/doctype/pos_settings/pos_settings.json
+++ b/erpnext/accounts/doctype/pos_settings/pos_settings.json
@@ -5,24 +5,11 @@
  "editable_grid": 1,
  "engine": "InnoDB",
  "field_order": [
-  "use_pos_in_offline_mode",
-  "section_break_2",
-  "fields"
+  "invoice_fields"
  ],
  "fields": [
   {
-   "default": "0",
-   "fieldname": "use_pos_in_offline_mode",
-   "fieldtype": "Check",
-   "label": "Use POS in Offline Mode"
-  },
-  {
-   "fieldname": "section_break_2",
-   "fieldtype": "Section Break"
-  },
-  {
-   "depends_on": "eval:!doc.use_pos_in_offline_mode",
-   "fieldname": "fields",
+   "fieldname": "invoice_fields",
    "fieldtype": "Table",
    "label": "POS Field",
    "options": "POS Field"
@@ -30,7 +17,7 @@
  ],
  "issingle": 1,
  "links": [],
- "modified": "2019-12-26 11:50:47.122997",
+ "modified": "2020-06-01 15:46:41.478928",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "POS Settings",
diff --git a/erpnext/accounts/doctype/pricing_rule/pricing_rule.py b/erpnext/accounts/doctype/pricing_rule/pricing_rule.py
index ead300e..d90ae28 100644
--- a/erpnext/accounts/doctype/pricing_rule/pricing_rule.py
+++ b/erpnext/accounts/doctype/pricing_rule/pricing_rule.py
@@ -276,7 +276,7 @@
 
 		item_details.has_pricing_rule = 1
 
-		item_details.pricing_rules = ','.join([d.pricing_rule for d in rules])
+		item_details.pricing_rules = frappe.as_json([d.pricing_rule for d in rules])
 
 		if not doc: return item_details
 
@@ -366,7 +366,7 @@
 
 def remove_pricing_rule_for_item(pricing_rules, item_details, item_code=None):
 	from erpnext.accounts.doctype.pricing_rule.utils import get_pricing_rule_items
-	for d in pricing_rules.split(','):
+	for d in json.loads(pricing_rules):
 		if not d or not frappe.db.exists("Pricing Rule", d): continue
 		pricing_rule = frappe.get_cached_doc('Pricing Rule', d)
 
@@ -432,6 +432,7 @@
 
 	return doc
 
+@frappe.whitelist()
 def get_item_uoms(doctype, txt, searchfield, start, page_len, filters):
 	items = [filters.get('value')]
 	if filters.get('apply_on') != 'Item Code':
@@ -442,4 +443,4 @@
 
 	return frappe.get_all('UOM Conversion Detail',
 		filters = {'parent': ('in', items), 'uom': ("like", "{0}%".format(txt))},
-		fields = ["distinct uom"], as_list=1)
\ No newline at end of file
+		fields = ["distinct uom"], as_list=1)
diff --git a/erpnext/accounts/doctype/pricing_rule/utils.py b/erpnext/accounts/doctype/pricing_rule/utils.py
index 53115f9..3fd316f 100644
--- a/erpnext/accounts/doctype/pricing_rule/utils.py
+++ b/erpnext/accounts/doctype/pricing_rule/utils.py
@@ -319,7 +319,9 @@
 	filtered_rules = []
 	for field in field_set:
 		if args.get(field):
-			filtered_rules = filter(lambda x: x[field]==args[field], pricing_rules)
+			# filter function always returns a filter object even if empty
+			# list conversion is necessary to check for an empty result
+			filtered_rules = list(filter(lambda x: x.get(field)==args.get(field), pricing_rules))
 			if filtered_rules: break
 
 	return filtered_rules or pricing_rules
@@ -446,7 +448,7 @@
 				doc.set_missing_values()
 
 def get_applied_pricing_rules(item_row):
-	return (item_row.get("pricing_rules").split(',')
+	return (json.loads(item_row.get("pricing_rules"))
 		if item_row.get("pricing_rules") else [])
 
 def get_product_discount_rule(pricing_rule, item_details, args=None, doc=None):
diff --git a/erpnext/accounts/doctype/process_deferred_accounting/process_deferred_accounting.js b/erpnext/accounts/doctype/process_deferred_accounting/process_deferred_accounting.js
index 975c60c..2800c19 100644
--- a/erpnext/accounts/doctype/process_deferred_accounting/process_deferred_accounting.js
+++ b/erpnext/accounts/doctype/process_deferred_accounting/process_deferred_accounting.js
@@ -10,6 +10,18 @@
 				}
 			};
 		});
+
+		if (frm.doc.company) {
+			frm.set_query("account", function() {
+				return {
+					filters: {
+						'company': frm.doc.company,
+						'root_type': 'Liability',
+						'is_group': 0
+					}
+				};
+			});
+		}
 	},
 
 	validate: function() {
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
index 829c34d..639ef6c 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
@@ -170,9 +170,7 @@
    "hidden": 1,
    "label": "Title",
    "no_copy": 1,
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "fieldname": "naming_series",
@@ -184,9 +182,7 @@
    "options": "ACC-PINV-.YYYY.-",
    "print_hide": 1,
    "reqd": 1,
-   "set_only_once": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "set_only_once": 1
   },
   {
    "fieldname": "supplier",
@@ -198,9 +194,7 @@
    "options": "Supplier",
    "print_hide": 1,
    "reqd": 1,
-   "search_index": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "search_index": 1
   },
   {
    "bold": 1,
@@ -212,9 +206,7 @@
    "label": "Supplier Name",
    "oldfieldname": "supplier_name",
    "oldfieldtype": "Data",
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fetch_from": "supplier.tax_id",
@@ -222,27 +214,21 @@
    "fieldtype": "Read Only",
    "label": "Tax Id",
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "due_date",
    "fieldtype": "Date",
    "label": "Due Date",
    "oldfieldname": "due_date",
-   "oldfieldtype": "Date",
-   "show_days": 1,
-   "show_seconds": 1
+   "oldfieldtype": "Date"
   },
   {
    "default": "0",
    "fieldname": "is_paid",
    "fieldtype": "Check",
    "label": "Is Paid",
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "default": "0",
@@ -250,25 +236,19 @@
    "fieldtype": "Check",
    "label": "Is Return (Debit Note)",
    "no_copy": 1,
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "default": "0",
    "fieldname": "apply_tds",
    "fieldtype": "Check",
    "label": "Apply Tax Withholding Amount",
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "fieldname": "column_break1",
    "fieldtype": "Column Break",
    "oldfieldtype": "Column Break",
-   "show_days": 1,
-   "show_seconds": 1,
    "width": "50%"
   },
   {
@@ -278,17 +258,13 @@
    "label": "Company",
    "options": "Company",
    "print_hide": 1,
-   "remember_last_selected_value": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "remember_last_selected_value": 1
   },
   {
    "fieldname": "cost_center",
    "fieldtype": "Link",
    "label": "Cost Center",
-   "options": "Cost Center",
-   "show_days": 1,
-   "show_seconds": 1
+   "options": "Cost Center"
   },
   {
    "default": "Today",
@@ -300,9 +276,7 @@
    "oldfieldtype": "Date",
    "print_hide": 1,
    "reqd": 1,
-   "search_index": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "search_index": 1
   },
   {
    "fieldname": "posting_time",
@@ -311,8 +285,6 @@
    "no_copy": 1,
    "print_hide": 1,
    "print_width": "100px",
-   "show_days": 1,
-   "show_seconds": 1,
    "width": "100px"
   },
   {
@@ -321,9 +293,7 @@
    "fieldname": "set_posting_time",
    "fieldtype": "Check",
    "label": "Edit Posting Date and Time",
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "fieldname": "amended_from",
@@ -335,58 +305,44 @@
    "oldfieldtype": "Link",
    "options": "Purchase Invoice",
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "collapsible": 1,
    "collapsible_depends_on": "eval:doc.on_hold",
    "fieldname": "sb_14",
    "fieldtype": "Section Break",
-   "label": "Hold Invoice",
-   "show_days": 1,
-   "show_seconds": 1
+   "label": "Hold Invoice"
   },
   {
    "default": "0",
    "fieldname": "on_hold",
    "fieldtype": "Check",
-   "label": "Hold Invoice",
-   "show_days": 1,
-   "show_seconds": 1
+   "label": "Hold Invoice"
   },
   {
    "depends_on": "eval:doc.on_hold",
    "description": "Once set, this invoice will be on hold till the set date",
    "fieldname": "release_date",
    "fieldtype": "Date",
-   "label": "Release Date",
-   "show_days": 1,
-   "show_seconds": 1
+   "label": "Release Date"
   },
   {
    "fieldname": "cb_17",
-   "fieldtype": "Column Break",
-   "show_days": 1,
-   "show_seconds": 1
+   "fieldtype": "Column Break"
   },
   {
    "depends_on": "eval:doc.on_hold",
    "fieldname": "hold_comment",
    "fieldtype": "Small Text",
-   "label": "Reason For Putting On Hold",
-   "show_days": 1,
-   "show_seconds": 1
+   "label": "Reason For Putting On Hold"
   },
   {
    "collapsible": 1,
    "collapsible_depends_on": "bill_no",
    "fieldname": "supplier_invoice_details",
    "fieldtype": "Section Break",
-   "label": "Supplier Invoice Details",
-   "show_days": 1,
-   "show_seconds": 1
+   "label": "Supplier Invoice Details"
   },
   {
    "fieldname": "bill_no",
@@ -394,15 +350,11 @@
    "label": "Supplier Invoice No",
    "oldfieldname": "bill_no",
    "oldfieldtype": "Data",
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "fieldname": "column_break_15",
-   "fieldtype": "Column Break",
-   "show_days": 1,
-   "show_seconds": 1
+   "fieldtype": "Column Break"
   },
   {
    "fieldname": "bill_date",
@@ -410,17 +362,13 @@
    "label": "Supplier Invoice Date",
    "oldfieldname": "bill_date",
    "oldfieldtype": "Date",
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "depends_on": "return_against",
    "fieldname": "returns",
    "fieldtype": "Section Break",
-   "label": "Returns",
-   "show_days": 1,
-   "show_seconds": 1
+   "label": "Returns"
   },
   {
    "depends_on": "return_against",
@@ -430,34 +378,26 @@
    "no_copy": 1,
    "options": "Purchase Invoice",
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "collapsible": 1,
    "fieldname": "section_addresses",
    "fieldtype": "Section Break",
-   "label": "Address and Contact",
-   "show_days": 1,
-   "show_seconds": 1
+   "label": "Address and Contact"
   },
   {
    "fieldname": "supplier_address",
    "fieldtype": "Link",
    "label": "Select Supplier Address",
    "options": "Address",
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "fieldname": "address_display",
    "fieldtype": "Small Text",
    "label": "Address",
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "contact_person",
@@ -465,67 +405,51 @@
    "in_global_search": 1,
    "label": "Contact Person",
    "options": "Contact",
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "fieldname": "contact_display",
    "fieldtype": "Small Text",
    "label": "Contact",
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "contact_mobile",
    "fieldtype": "Small Text",
    "label": "Mobile No",
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "contact_email",
    "fieldtype": "Small Text",
    "label": "Contact Email",
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "col_break_address",
-   "fieldtype": "Column Break",
-   "show_days": 1,
-   "show_seconds": 1
+   "fieldtype": "Column Break"
   },
   {
    "fieldname": "shipping_address",
    "fieldtype": "Link",
    "label": "Select Shipping Address",
    "options": "Address",
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "fieldname": "shipping_address_display",
    "fieldtype": "Small Text",
    "label": "Shipping Address",
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "collapsible": 1,
    "fieldname": "currency_and_price_list",
    "fieldtype": "Section Break",
    "label": "Currency and Price List",
-   "options": "fa fa-tag",
-   "show_days": 1,
-   "show_seconds": 1
+   "options": "fa fa-tag"
   },
   {
    "fieldname": "currency",
@@ -534,9 +458,7 @@
    "oldfieldname": "currency",
    "oldfieldtype": "Select",
    "options": "Currency",
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "fieldname": "conversion_rate",
@@ -545,24 +467,18 @@
    "oldfieldname": "conversion_rate",
    "oldfieldtype": "Currency",
    "precision": "9",
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "fieldname": "column_break2",
-   "fieldtype": "Column Break",
-   "show_days": 1,
-   "show_seconds": 1
+   "fieldtype": "Column Break"
   },
   {
    "fieldname": "buying_price_list",
    "fieldtype": "Link",
    "label": "Price List",
    "options": "Price List",
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "fieldname": "price_list_currency",
@@ -570,18 +486,14 @@
    "label": "Price List Currency",
    "options": "Currency",
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "plc_conversion_rate",
    "fieldtype": "Float",
    "label": "Price List Exchange Rate",
    "precision": "9",
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "default": "0",
@@ -590,15 +502,11 @@
    "label": "Ignore Pricing Rule",
    "no_copy": 1,
    "permlevel": 1,
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "fieldname": "sec_warehouse",
-   "fieldtype": "Section Break",
-   "show_days": 1,
-   "show_seconds": 1
+   "fieldtype": "Section Break"
   },
   {
    "depends_on": "update_stock",
@@ -606,9 +514,7 @@
    "fieldtype": "Link",
    "label": "Set Accepted Warehouse",
    "options": "Warehouse",
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "depends_on": "update_stock",
@@ -618,15 +524,11 @@
    "label": "Rejected Warehouse",
    "no_copy": 1,
    "options": "Warehouse",
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "fieldname": "col_break_warehouse",
-   "fieldtype": "Column Break",
-   "show_days": 1,
-   "show_seconds": 1
+   "fieldtype": "Column Break"
   },
   {
    "default": "No",
@@ -634,9 +536,7 @@
    "fieldtype": "Select",
    "label": "Raw Materials Supplied",
    "options": "No\nYes",
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "depends_on": "eval:doc.is_subcontracted==\"Yes\"",
@@ -647,33 +547,25 @@
    "options": "Warehouse",
    "print_hide": 1,
    "print_width": "50px",
-   "show_days": 1,
-   "show_seconds": 1,
    "width": "50px"
   },
   {
    "fieldname": "items_section",
    "fieldtype": "Section Break",
    "oldfieldtype": "Section Break",
-   "options": "fa fa-shopping-cart",
-   "show_days": 1,
-   "show_seconds": 1
+   "options": "fa fa-shopping-cart"
   },
   {
    "default": "0",
    "fieldname": "update_stock",
    "fieldtype": "Check",
    "label": "Update Stock",
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "fieldname": "scan_barcode",
    "fieldtype": "Data",
-   "label": "Scan Barcode",
-   "show_days": 1,
-   "show_seconds": 1
+   "label": "Scan Barcode"
   },
   {
    "allow_bulk_edit": 1,
@@ -683,56 +575,42 @@
    "oldfieldname": "entries",
    "oldfieldtype": "Table",
    "options": "Purchase Invoice Item",
-   "reqd": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "reqd": 1
   },
   {
    "fieldname": "pricing_rule_details",
    "fieldtype": "Section Break",
-   "label": "Pricing Rules",
-   "show_days": 1,
-   "show_seconds": 1
+   "label": "Pricing Rules"
   },
   {
    "fieldname": "pricing_rules",
    "fieldtype": "Table",
    "label": "Pricing Rule Detail",
    "options": "Pricing Rule Detail",
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "collapsible_depends_on": "supplied_items",
    "fieldname": "raw_materials_supplied",
    "fieldtype": "Section Break",
-   "label": "Raw Materials Supplied",
-   "show_days": 1,
-   "show_seconds": 1
+   "label": "Raw Materials Supplied"
   },
   {
    "fieldname": "supplied_items",
    "fieldtype": "Table",
    "label": "Supplied Items",
    "options": "Purchase Receipt Item Supplied",
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "section_break_26",
-   "fieldtype": "Section Break",
-   "show_days": 1,
-   "show_seconds": 1
+   "fieldtype": "Section Break"
   },
   {
    "fieldname": "total_qty",
    "fieldtype": "Float",
    "label": "Total Quantity",
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "base_total",
@@ -740,9 +618,7 @@
    "label": "Total (Company Currency)",
    "options": "Company:company:default_currency",
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "base_net_total",
@@ -752,24 +628,18 @@
    "oldfieldtype": "Currency",
    "options": "Company:company:default_currency",
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "column_break_28",
-   "fieldtype": "Column Break",
-   "show_days": 1,
-   "show_seconds": 1
+   "fieldtype": "Column Break"
   },
   {
    "fieldname": "total",
    "fieldtype": "Currency",
    "label": "Total",
    "options": "currency",
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "net_total",
@@ -779,56 +649,42 @@
    "oldfieldtype": "Currency",
    "options": "currency",
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "total_net_weight",
    "fieldtype": "Float",
    "label": "Total Net Weight",
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "taxes_section",
    "fieldtype": "Section Break",
    "oldfieldtype": "Section Break",
-   "options": "fa fa-money",
-   "show_days": 1,
-   "show_seconds": 1
+   "options": "fa fa-money"
   },
   {
    "fieldname": "tax_category",
    "fieldtype": "Link",
    "label": "Tax Category",
    "options": "Tax Category",
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "fieldname": "column_break_49",
-   "fieldtype": "Column Break",
-   "show_days": 1,
-   "show_seconds": 1
+   "fieldtype": "Column Break"
   },
   {
    "fieldname": "shipping_rule",
    "fieldtype": "Link",
    "label": "Shipping Rule",
    "options": "Shipping Rule",
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "fieldname": "section_break_51",
-   "fieldtype": "Section Break",
-   "show_days": 1,
-   "show_seconds": 1
+   "fieldtype": "Section Break"
   },
   {
    "fieldname": "taxes_and_charges",
@@ -837,9 +693,7 @@
    "oldfieldname": "purchase_other_charges",
    "oldfieldtype": "Link",
    "options": "Purchase Taxes and Charges Template",
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "fieldname": "taxes",
@@ -847,17 +701,13 @@
    "label": "Purchase Taxes and Charges",
    "oldfieldname": "purchase_tax_details",
    "oldfieldtype": "Table",
-   "options": "Purchase Taxes and Charges",
-   "show_days": 1,
-   "show_seconds": 1
+   "options": "Purchase Taxes and Charges"
   },
   {
    "collapsible": 1,
    "fieldname": "sec_tax_breakup",
    "fieldtype": "Section Break",
-   "label": "Tax Breakup",
-   "show_days": 1,
-   "show_seconds": 1
+   "label": "Tax Breakup"
   },
   {
    "fieldname": "other_charges_calculation",
@@ -866,17 +716,13 @@
    "no_copy": 1,
    "oldfieldtype": "HTML",
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "totals",
    "fieldtype": "Section Break",
    "oldfieldtype": "Section Break",
-   "options": "fa fa-money",
-   "show_days": 1,
-   "show_seconds": 1
+   "options": "fa fa-money"
   },
   {
    "fieldname": "base_taxes_and_charges_added",
@@ -886,9 +732,7 @@
    "oldfieldtype": "Currency",
    "options": "Company:company:default_currency",
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "base_taxes_and_charges_deducted",
@@ -898,9 +742,7 @@
    "oldfieldtype": "Currency",
    "options": "Company:company:default_currency",
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "base_total_taxes_and_charges",
@@ -910,15 +752,11 @@
    "oldfieldtype": "Currency",
    "options": "Company:company:default_currency",
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "column_break_40",
-   "fieldtype": "Column Break",
-   "show_days": 1,
-   "show_seconds": 1
+   "fieldtype": "Column Break"
   },
   {
    "fieldname": "taxes_and_charges_added",
@@ -928,9 +766,7 @@
    "oldfieldtype": "Currency",
    "options": "currency",
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "taxes_and_charges_deducted",
@@ -940,9 +776,7 @@
    "oldfieldtype": "Currency",
    "options": "currency",
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "total_taxes_and_charges",
@@ -950,18 +784,14 @@
    "label": "Total Taxes and Charges",
    "options": "currency",
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "collapsible": 1,
    "collapsible_depends_on": "discount_amount",
    "fieldname": "section_break_44",
    "fieldtype": "Section Break",
-   "label": "Additional Discount",
-   "show_days": 1,
-   "show_seconds": 1
+   "label": "Additional Discount"
   },
   {
    "default": "Grand Total",
@@ -969,9 +799,7 @@
    "fieldtype": "Select",
    "label": "Apply Additional Discount On",
    "options": "\nGrand Total\nNet Total",
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "fieldname": "base_discount_amount",
@@ -979,38 +807,28 @@
    "label": "Additional Discount Amount (Company Currency)",
    "options": "Company:company:default_currency",
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "column_break_46",
-   "fieldtype": "Column Break",
-   "show_days": 1,
-   "show_seconds": 1
+   "fieldtype": "Column Break"
   },
   {
    "fieldname": "additional_discount_percentage",
    "fieldtype": "Float",
    "label": "Additional Discount Percentage",
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "fieldname": "discount_amount",
    "fieldtype": "Currency",
    "label": "Additional Discount Amount",
    "options": "currency",
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "fieldname": "section_break_49",
-   "fieldtype": "Section Break",
-   "show_days": 1,
-   "show_seconds": 1
+   "fieldtype": "Section Break"
   },
   {
    "fieldname": "base_grand_total",
@@ -1020,9 +838,7 @@
    "oldfieldtype": "Currency",
    "options": "Company:company:default_currency",
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "base_rounding_adjustment",
@@ -1031,9 +847,7 @@
    "no_copy": 1,
    "options": "Company:company:default_currency",
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "depends_on": "eval:!doc.disable_rounded_total",
@@ -1043,28 +857,23 @@
    "no_copy": 1,
    "options": "Company:company:default_currency",
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "base_in_words",
    "fieldtype": "Data",
    "label": "In Words (Company Currency)",
+   "length": 240,
    "oldfieldname": "in_words",
    "oldfieldtype": "Data",
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "column_break8",
    "fieldtype": "Column Break",
    "oldfieldtype": "Column Break",
    "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1,
    "width": "50%"
   },
   {
@@ -1075,9 +884,7 @@
    "oldfieldname": "grand_total_import",
    "oldfieldtype": "Currency",
    "options": "currency",
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "rounding_adjustment",
@@ -1086,9 +893,7 @@
    "no_copy": 1,
    "options": "currency",
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "depends_on": "eval:!doc.disable_rounded_total",
@@ -1098,20 +903,17 @@
    "no_copy": 1,
    "options": "currency",
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "in_words",
    "fieldtype": "Data",
    "label": "In Words",
+   "length": 240,
    "oldfieldname": "in_words_import",
    "oldfieldtype": "Data",
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "total_advance",
@@ -1122,9 +924,7 @@
    "oldfieldtype": "Currency",
    "options": "party_account_currency",
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "outstanding_amount",
@@ -1135,18 +935,14 @@
    "oldfieldtype": "Currency",
    "options": "party_account_currency",
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "default": "0",
    "depends_on": "grand_total",
    "fieldname": "disable_rounded_total",
    "fieldtype": "Check",
-   "label": "Disable Rounded Total",
-   "show_days": 1,
-   "show_seconds": 1
+   "label": "Disable Rounded Total"
   },
   {
    "collapsible": 1,
@@ -1154,40 +950,30 @@
    "depends_on": "eval:doc.is_paid===1||(doc.advances && doc.advances.length>0)",
    "fieldname": "payments_section",
    "fieldtype": "Section Break",
-   "label": "Payments",
-   "show_days": 1,
-   "show_seconds": 1
+   "label": "Payments"
   },
   {
    "fieldname": "mode_of_payment",
    "fieldtype": "Link",
    "label": "Mode of Payment",
    "options": "Mode of Payment",
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "fieldname": "cash_bank_account",
    "fieldtype": "Link",
    "label": "Cash/Bank Account",
-   "options": "Account",
-   "show_days": 1,
-   "show_seconds": 1
+   "options": "Account"
   },
   {
    "fieldname": "clearance_date",
    "fieldtype": "Date",
    "hidden": 1,
-   "label": "Clearance Date",
-   "show_days": 1,
-   "show_seconds": 1
+   "label": "Clearance Date"
   },
   {
    "fieldname": "col_br_payments",
-   "fieldtype": "Column Break",
-   "show_days": 1,
-   "show_seconds": 1
+   "fieldtype": "Column Break"
   },
   {
    "depends_on": "is_paid",
@@ -1196,9 +982,7 @@
    "label": "Paid Amount",
    "no_copy": 1,
    "options": "currency",
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "fieldname": "base_paid_amount",
@@ -1207,9 +991,7 @@
    "no_copy": 1,
    "options": "Company:company:default_currency",
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "collapsible": 1,
@@ -1217,9 +999,7 @@
    "depends_on": "grand_total",
    "fieldname": "write_off",
    "fieldtype": "Section Break",
-   "label": "Write Off",
-   "show_days": 1,
-   "show_seconds": 1
+   "label": "Write Off"
   },
   {
    "fieldname": "write_off_amount",
@@ -1227,9 +1007,7 @@
    "label": "Write Off Amount",
    "no_copy": 1,
    "options": "currency",
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "fieldname": "base_write_off_amount",
@@ -1238,15 +1016,11 @@
    "no_copy": 1,
    "options": "Company:company:default_currency",
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "column_break_61",
-   "fieldtype": "Column Break",
-   "show_days": 1,
-   "show_seconds": 1
+   "fieldtype": "Column Break"
   },
   {
    "depends_on": "eval:flt(doc.write_off_amount)!=0",
@@ -1254,9 +1028,7 @@
    "fieldtype": "Link",
    "label": "Write Off Account",
    "options": "Account",
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "depends_on": "eval:flt(doc.write_off_amount)!=0",
@@ -1264,9 +1036,7 @@
    "fieldtype": "Link",
    "label": "Write Off Cost Center",
    "options": "Cost Center",
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "collapsible": 1,
@@ -1276,17 +1046,13 @@
    "label": "Advance Payments",
    "oldfieldtype": "Section Break",
    "options": "fa fa-money",
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "default": "0",
    "fieldname": "allocate_advances_automatically",
    "fieldtype": "Check",
-   "label": "Set Advances and Allocate (FIFO)",
-   "show_days": 1,
-   "show_seconds": 1
+   "label": "Set Advances and Allocate (FIFO)"
   },
   {
    "depends_on": "eval:!doc.allocate_advances_automatically",
@@ -1294,9 +1060,7 @@
    "fieldtype": "Button",
    "label": "Get Advances Paid",
    "oldfieldtype": "Button",
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "fieldname": "advances",
@@ -1306,26 +1070,20 @@
    "oldfieldname": "advance_allocation_details",
    "oldfieldtype": "Table",
    "options": "Purchase Invoice Advance",
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "collapsible": 1,
    "collapsible_depends_on": "eval:(!doc.is_return)",
    "fieldname": "payment_schedule_section",
    "fieldtype": "Section Break",
-   "label": "Payment Terms",
-   "show_days": 1,
-   "show_seconds": 1
+   "label": "Payment Terms"
   },
   {
    "fieldname": "payment_terms_template",
    "fieldtype": "Link",
    "label": "Payment Terms Template",
-   "options": "Payment Terms Template",
-   "show_days": 1,
-   "show_seconds": 1
+   "options": "Payment Terms Template"
   },
   {
    "fieldname": "payment_schedule",
@@ -1333,9 +1091,7 @@
    "label": "Payment Schedule",
    "no_copy": 1,
    "options": "Payment Schedule",
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "collapsible": 1,
@@ -1343,33 +1099,25 @@
    "fieldname": "terms_section_break",
    "fieldtype": "Section Break",
    "label": "Terms and Conditions",
-   "options": "fa fa-legal",
-   "show_days": 1,
-   "show_seconds": 1
+   "options": "fa fa-legal"
   },
   {
    "fieldname": "tc_name",
    "fieldtype": "Link",
    "label": "Terms",
    "options": "Terms and Conditions",
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "fieldname": "terms",
    "fieldtype": "Text Editor",
-   "label": "Terms and Conditions1",
-   "show_days": 1,
-   "show_seconds": 1
+   "label": "Terms and Conditions1"
   },
   {
    "collapsible": 1,
    "fieldname": "printing_settings",
    "fieldtype": "Section Break",
-   "label": "Printing Settings",
-   "show_days": 1,
-   "show_seconds": 1
+   "label": "Printing Settings"
   },
   {
    "allow_on_submit": 1,
@@ -1377,9 +1125,7 @@
    "fieldtype": "Link",
    "label": "Letter Head",
    "options": "Letter Head",
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "allow_on_submit": 1,
@@ -1387,15 +1133,11 @@
    "fieldname": "group_same_items",
    "fieldtype": "Check",
    "label": "Group same items",
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "fieldname": "column_break_112",
-   "fieldtype": "Column Break",
-   "show_days": 1,
-   "show_seconds": 1
+   "fieldtype": "Column Break"
   },
   {
    "allow_on_submit": 1,
@@ -1407,18 +1149,14 @@
    "oldfieldtype": "Link",
    "options": "Print Heading",
    "print_hide": 1,
-   "report_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "report_hide": 1
   },
   {
    "fieldname": "language",
    "fieldtype": "Data",
    "label": "Print Language",
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "collapsible": 1,
@@ -1427,9 +1165,7 @@
    "label": "More Information",
    "oldfieldtype": "Section Break",
    "options": "fa fa-file-text",
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "fieldname": "credit_to",
@@ -1440,9 +1176,7 @@
    "options": "Account",
    "print_hide": 1,
    "reqd": 1,
-   "search_index": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "search_index": 1
   },
   {
    "fieldname": "party_account_currency",
@@ -1452,9 +1186,7 @@
    "no_copy": 1,
    "options": "Currency",
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "default": "No",
@@ -1464,9 +1196,7 @@
    "oldfieldname": "is_opening",
    "oldfieldtype": "Select",
    "options": "No\nYes",
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "fieldname": "against_expense_account",
@@ -1476,15 +1206,11 @@
    "no_copy": 1,
    "oldfieldname": "against_expense_account",
    "oldfieldtype": "Small Text",
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "fieldname": "column_break_63",
-   "fieldtype": "Column Break",
-   "show_days": 1,
-   "show_seconds": 1
+   "fieldtype": "Column Break"
   },
   {
    "default": "Draft",
@@ -1493,18 +1219,14 @@
    "in_standard_filter": 1,
    "label": "Status",
    "options": "\nDraft\nReturn\nDebit Note Issued\nSubmitted\nPaid\nUnpaid\nOverdue\nCancelled",
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "fieldname": "inter_company_invoice_reference",
    "fieldtype": "Link",
    "label": "Inter Company Invoice Reference",
    "options": "Sales Invoice",
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "remarks",
@@ -1513,18 +1235,14 @@
    "no_copy": 1,
    "oldfieldname": "remarks",
    "oldfieldtype": "Text",
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "collapsible": 1,
    "fieldname": "subscription_section",
    "fieldtype": "Section Break",
    "label": "Subscription Section",
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "allow_on_submit": 1,
@@ -1533,9 +1251,7 @@
    "fieldtype": "Date",
    "label": "From Date",
    "no_copy": 1,
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "allow_on_submit": 1,
@@ -1544,15 +1260,11 @@
    "fieldtype": "Date",
    "label": "To Date",
    "no_copy": 1,
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "fieldname": "column_break_114",
-   "fieldtype": "Column Break",
-   "show_days": 1,
-   "show_seconds": 1
+   "fieldtype": "Column Break"
   },
   {
    "fieldname": "auto_repeat",
@@ -1561,32 +1273,24 @@
    "no_copy": 1,
    "options": "Auto Repeat",
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "allow_on_submit": 1,
    "depends_on": "eval: doc.auto_repeat",
    "fieldname": "update_auto_repeat_reference",
    "fieldtype": "Button",
-   "label": "Update Auto Repeat Reference",
-   "show_days": 1,
-   "show_seconds": 1
+   "label": "Update Auto Repeat Reference"
   },
   {
    "collapsible": 1,
    "fieldname": "accounting_dimensions_section",
    "fieldtype": "Section Break",
-   "label": "Accounting Dimensions ",
-   "show_days": 1,
-   "show_seconds": 1
+   "label": "Accounting Dimensions "
   },
   {
    "fieldname": "dimension_col_break",
-   "fieldtype": "Column Break",
-   "show_days": 1,
-   "show_seconds": 1
+   "fieldtype": "Column Break"
   },
   {
    "default": "0",
@@ -1594,9 +1298,7 @@
    "fieldname": "is_internal_supplier",
    "fieldtype": "Check",
    "label": "Is Internal Supplier",
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "tax_withholding_category",
@@ -1604,32 +1306,26 @@
    "hidden": 1,
    "label": "Tax Withholding Category",
    "options": "Tax Withholding Category",
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "fieldname": "billing_address",
    "fieldtype": "Link",
    "label": "Select Billing Address",
-   "options": "Address",
-   "show_days": 1,
-   "show_seconds": 1
+   "options": "Address"
   },
   {
    "fieldname": "billing_address_display",
    "fieldtype": "Small Text",
    "label": "Billing Address",
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   }
  ],
  "icon": "fa fa-file-text",
  "idx": 204,
  "is_submittable": 1,
  "links": [],
- "modified": "2020-06-13 22:26:30.800199",
+ "modified": "2020-07-18 05:06:08.488761",
  "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 870718c..7b1062f 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
@@ -438,6 +438,8 @@
 
 		self.make_tax_gl_entries(gl_entries)
 
+		gl_entries = make_regional_gl_entries(gl_entries, self)
+
 		gl_entries = merge_similar_entries(gl_entries)
 
 		self.make_payment_gl_entries(gl_entries)
@@ -476,6 +478,7 @@
 						if self.party_account_currency==self.company_currency else grand_total,
 					"against_voucher": self.return_against if cint(self.is_return) and self.return_against else self.name,
 					"against_voucher_type": self.doctype,
+					"project": self.project,
 					"cost_center": self.cost_center
 				}, self.party_account_currency, item=self)
 			)
@@ -516,6 +519,7 @@
 							"account":  warehouse_account[item.warehouse]['account'],
 							"against": warehouse_account[item.from_warehouse]["account"],
 							"cost_center": item.cost_center,
+							"project": item.project or self.project,
 							"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
 							"debit": warehouse_debit_amount,
 						}, warehouse_account[item.warehouse]["account_currency"], item=item))
@@ -525,6 +529,7 @@
 							"account":  warehouse_account[item.from_warehouse]['account'],
 							"against": warehouse_account[item.warehouse]["account"],
 							"cost_center": item.cost_center,
+							"project": item.project or self.project,
 							"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
 							"debit": -1 * flt(item.base_net_amount, item.precision("base_net_amount")),
 						}, warehouse_account[item.from_warehouse]["account_currency"], item=item))
@@ -548,7 +553,7 @@
 								"debit": warehouse_debit_amount,
 								"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
 								"cost_center": item.cost_center,
-								"project": item.project
+								"project": item.project or self.project
 							}, account_currency, item=item)
 						)
 
@@ -561,7 +566,7 @@
 								"cost_center": item.cost_center,
 								"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
 								"credit": flt(amount),
-								"project": item.project
+								"project": item.project or self.project
 							}, item=item))
 
 					# sub-contracting warehouse
@@ -574,6 +579,7 @@
 							"account": supplier_warehouse_account,
 							"against": item.expense_account,
 							"cost_center": item.cost_center,
+							"project": item.project or self.project,
 							"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
 							"credit": flt(item.rm_supp_cost)
 						}, warehouse_account[self.supplier_warehouse]["account_currency"], item=item))
@@ -587,12 +593,26 @@
 					else:
 						amount = flt(item.base_net_amount + item.item_tax_amount, item.precision("base_net_amount"))
 
+					auto_accounting_for_non_stock_items = cint(frappe.db.get_value('Company', self.company, 'enable_perpetual_inventory_for_non_stock_items'))
+
+					if auto_accounting_for_non_stock_items:
+						service_received_but_not_billed_account = self.get_company_default("service_received_but_not_billed")
+
+						if item.purchase_receipt:
+							# Post reverse entry for Stock-Received-But-Not-Billed if it is booked in Purchase Receipt
+							expense_booked_in_pr = frappe.db.get_value('GL Entry', {'is_cancelled': 0,
+								'voucher_type': 'Purchase Receipt', 'voucher_no': item.purchase_receipt, 'voucher_detail_no': item.pr_detail,
+								'account':service_received_but_not_billed_account}, ['name'])
+
+							if expense_booked_in_pr:
+								expense_account = service_received_but_not_billed_account
+
 					gl_entries.append(self.get_gl_dict({
 							"account": expense_account,
 							"against": self.supplier,
 							"debit": amount,
 							"cost_center": item.cost_center,
-							"project": item.project
+							"project": item.project or self.project
 						}, account_currency, item=item))
 
 					# If asset is bought through this document and not linked to PR
@@ -605,7 +625,7 @@
 							"cost_center": item.cost_center,
 							"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
 							"credit": flt(item.landed_cost_voucher_amount),
-							"project": item.project
+							"project": item.project or self.project
 						}, item=item))
 
 						gl_entries.append(self.get_gl_dict({
@@ -614,7 +634,7 @@
 							"cost_center": item.cost_center,
 							"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
 							"debit": flt(item.landed_cost_voucher_amount),
-							"project": item.project
+							"project": item.project or self.project
 						}, item=item))
 
 						# update gross amount of asset bought through this document
@@ -640,7 +660,8 @@
 									"against": self.supplier,
 									"debit": flt(item.item_tax_amount, item.precision("item_tax_amount")),
 									"remarks": self.remarks or "Accounting Entry for Stock",
-									"cost_center": self.cost_center
+									"cost_center": self.cost_center,
+									"project": item.project or self.project
 								}, item=item)
 							)
 
@@ -669,7 +690,8 @@
 						"debit": base_asset_amount,
 						"debit_in_account_currency": (base_asset_amount
 							if arbnb_currency == self.company_currency else asset_amount),
-						"cost_center": item.cost_center
+						"cost_center": item.cost_center,
+						"project": item.project or self.project
 					}, item=item))
 
 					if item.item_tax_amount:
@@ -679,6 +701,7 @@
 							"against": self.supplier,
 							"remarks": self.get("remarks") or _("Accounting Entry for Asset"),
 							"cost_center": item.cost_center,
+							"project": item.project or self.project,
 							"credit": item.item_tax_amount,
 							"credit_in_account_currency": (item.item_tax_amount
 								if asset_eiiav_currency == self.company_currency else
@@ -695,7 +718,8 @@
 						"debit": base_asset_amount,
 						"debit_in_account_currency": (base_asset_amount
 							if cwip_account_currency == self.company_currency else asset_amount),
-						"cost_center": self.cost_center
+						"cost_center": self.cost_center,
+						"project": item.project or self.project
 					}, item=item))
 
 					if item.item_tax_amount and not cint(erpnext.is_perpetual_inventory_enabled(self.company)):
@@ -706,6 +730,7 @@
 							"remarks": self.get("remarks") or _("Accounting Entry for Asset"),
 							"cost_center": item.cost_center,
 							"credit": item.item_tax_amount,
+							"project": item.project or self.project,
 							"credit_in_account_currency": (item.item_tax_amount
 								if asset_eiiav_currency == self.company_currency else
 									item.item_tax_amount / self.conversion_rate)
@@ -721,7 +746,7 @@
 								"cost_center": item.cost_center,
 								"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
 								"credit": flt(item.landed_cost_voucher_amount),
-								"project": item.project
+								"project": item.project or self.project
 							}, item=item))
 
 							gl_entries.append(self.get_gl_dict({
@@ -730,7 +755,7 @@
 								"cost_center": item.cost_center,
 								"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
 								"debit": flt(item.landed_cost_voucher_amount),
-								"project": item.project
+								"project": item.project or self.project
 							}, item=item))
 
 						# update gross amount of assets bought through this document
@@ -765,7 +790,7 @@
 					"debit": stock_adjustment_amt,
 					"remarks": self.get("remarks") or _("Stock Adjustment"),
 					"cost_center": item.cost_center,
-					"project": item.project
+					"project": item.project or self.project
 				}, account_currency, item=item)
 			)
 
@@ -857,7 +882,8 @@
 						if self.party_account_currency==self.company_currency else self.paid_amount,
 					"against_voucher": self.return_against if cint(self.is_return) and self.return_against else self.name,
 					"against_voucher_type": self.doctype,
-					"cost_center": self.cost_center
+					"cost_center": self.cost_center,
+					"project": self.project
 				}, self.party_account_currency, item=self)
 			)
 
@@ -889,7 +915,8 @@
 						if self.party_account_currency==self.company_currency else self.write_off_amount,
 					"against_voucher": self.return_against if cint(self.is_return) and self.return_against else self.name,
 					"against_voucher_type": self.doctype,
-					"cost_center": self.cost_center
+					"cost_center": self.cost_center,
+					"project": self.project
 				}, self.party_account_currency, item=self)
 			)
 			gl_entries.append(
@@ -1083,6 +1110,10 @@
 	})
 	return list_context
 
+@erpnext.allow_regional
+def make_regional_gl_entries(gl_entries, doc):
+	return gl_entries
+
 @frappe.whitelist()
 def make_debit_note(source_name, target_doc=None):
 	from erpnext.controllers.sales_and_purchase_return import make_return_doc
diff --git a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
index 6170005..9a666bf 100644
--- a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
@@ -7,14 +7,16 @@
 import frappe, erpnext
 import frappe.model
 from erpnext.accounts.doctype.payment_entry.payment_entry import get_payment_entry
-from frappe.utils import cint, flt, today, nowdate, add_days
+from frappe.utils import cint, flt, today, nowdate, add_days, getdate
 import frappe.defaults
 from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import set_perpetual_inventory, \
 	test_records as pr_test_records, make_purchase_receipt, get_taxes
 from erpnext.controllers.accounts_controller import get_payment_terms
 from erpnext.exceptions import InvalidCurrency
 from erpnext.stock.doctype.stock_entry.test_stock_entry import get_qty_after_transaction
-from erpnext.accounts.doctype.account.test_account import get_inventory_account
+from erpnext.projects.doctype.project.test_project import make_project
+from erpnext.accounts.doctype.account.test_account import get_inventory_account, create_account
+from erpnext.stock.doctype.item.test_item import create_item
 
 test_dependencies = ["Item", "Cost Center", "Payment Term", "Payment Terms Template"]
 test_ignore = ["Serial No"]
@@ -434,6 +436,8 @@
 		)
 
 	def test_total_purchase_cost_for_project(self):
+		make_project({'project_name':'_Test Project'})
+
 		existing_purchase_cost = frappe.db.sql("""select sum(base_net_amount)
 			from `tabPurchase Invoice Item` where project = '_Test Project' and docstatus=1""")
 		existing_purchase_cost = existing_purchase_cost and existing_purchase_cost[0][0] or 0
@@ -807,11 +811,8 @@
 		pi_doc = frappe.get_doc('Purchase Invoice', pi.name)
 		self.assertEqual(pi_doc.outstanding_amount, 0)
 
-	def test_purchase_invoice_for_enable_allow_cost_center_in_entry_of_bs_account(self):
+	def test_purchase_invoice_with_cost_center(self):
 		from erpnext.accounts.doctype.cost_center.test_cost_center import create_cost_center
-		accounts_settings = frappe.get_doc('Accounts Settings', 'Accounts Settings')
-		accounts_settings.allow_cost_center_in_entry_of_bs_account = 1
-		accounts_settings.save()
 		cost_center = "_Test Cost Center for BS Account - _TC"
 		create_cost_center(cost_center_name="_Test Cost Center for BS Account", company="_Test Company")
 
@@ -837,13 +838,7 @@
 		for gle in gl_entries:
 			self.assertEqual(expected_values[gle.account]["cost_center"], gle.cost_center)
 
-		accounts_settings.allow_cost_center_in_entry_of_bs_account = 0
-		accounts_settings.save()
-
-	def test_purchase_invoice_for_disable_allow_cost_center_in_entry_of_bs_account(self):
-		accounts_settings = frappe.get_doc('Accounts Settings', 'Accounts Settings')
-		accounts_settings.allow_cost_center_in_entry_of_bs_account = 0
-		accounts_settings.save()
+	def test_purchase_invoice_without_cost_center(self):
 		cost_center = "_Test Cost Center - _TC"
 		pi =  make_purchase_invoice(credit_to="Creditors - _TC")
 
@@ -866,6 +861,104 @@
 		for gle in gl_entries:
 			self.assertEqual(expected_values[gle.account]["cost_center"], gle.cost_center)
 
+	def test_purchase_invoice_with_project_link(self):
+		project = make_project({
+			'project_name': 'Purchase Invoice Project',
+			'project_template_name': 'Test Project Template',
+			'start_date': '2020-01-01'
+		})
+		item_project = make_project({
+			'project_name': 'Purchase Invoice Item Project',
+			'project_template_name': 'Test Project Template',
+			'start_date': '2019-06-01'
+		})
+
+		pi = make_purchase_invoice(credit_to="Creditors - _TC" ,do_not_save=1)
+		pi.items[0].project = item_project.project_name
+		pi.project = project.project_name
+
+		pi.submit()
+
+		expected_values = {
+			"Creditors - _TC": {
+				"project": project.project_name
+			},
+			"_Test Account Cost for Goods Sold - _TC": {
+				"project": item_project.project_name
+			}
+		}
+
+		gl_entries = frappe.db.sql("""select account, cost_center, project, account_currency, debit, credit,
+			debit_in_account_currency, credit_in_account_currency
+			from `tabGL Entry` where voucher_type='Purchase Invoice' and voucher_no=%s
+			order by account asc""", pi.name, as_dict=1)
+
+		self.assertTrue(gl_entries)
+
+		for gle in gl_entries:
+			self.assertEqual(expected_values[gle.account]["project"], gle.project)
+
+	def test_deferred_expense_via_journal_entry(self):
+		deferred_account = create_account(account_name="Deferred Expense",
+			parent_account="Current Assets - _TC", company="_Test Company")
+
+		acc_settings = frappe.get_doc('Accounts Settings', 'Accounts Settings')
+		acc_settings.book_deferred_entries_via_journal_entry = 1
+		acc_settings.submit_journal_entries = 1
+		acc_settings.save()
+
+		item = create_item("_Test Item for Deferred Accounting")
+		item.enable_deferred_expense = 1
+		item.deferred_expense_account = deferred_account
+		item.save()
+
+		pi = make_purchase_invoice(item=item.name, qty=1, rate=100, do_not_save=True)
+		pi.set_posting_time = 1
+		pi.posting_date = '2019-03-15'
+		pi.items[0].enable_deferred_expense = 1
+		pi.items[0].service_start_date = "2019-01-10"
+		pi.items[0].service_end_date = "2019-03-15"
+		pi.items[0].deferred_expense_account = deferred_account
+		pi.save()
+		pi.submit()
+
+		pda1 = frappe.get_doc(dict(
+			doctype='Process Deferred Accounting',
+			posting_date=nowdate(),
+			start_date="2019-01-01",
+			end_date="2019-03-31",
+			type="Expense",
+			company="_Test Company"
+		))
+
+		pda1.insert()
+		pda1.submit()
+
+		expected_gle = [
+			["_Test Account Cost for Goods Sold - _TC", 0.0, 33.85, "2019-01-31"],
+			[deferred_account, 33.85, 0.0, "2019-01-31"],
+			["_Test Account Cost for Goods Sold - _TC", 0.0, 43.08, "2019-02-28"],
+			[deferred_account, 43.08, 0.0, "2019-02-28"],
+			["_Test Account Cost for Goods Sold - _TC", 0.0, 23.07, "2019-03-15"],
+			[deferred_account, 23.07, 0.0, "2019-03-15"]
+		]
+
+		gl_entries = gl_entries = frappe.db.sql("""select account, debit, credit, posting_date
+			from `tabGL Entry`
+			where voucher_type='Journal Entry' and voucher_detail_no=%s and posting_date <= %s
+			order by posting_date asc, account asc""", (pi.items[0].name, pi.posting_date), as_dict=1)
+
+		for i, gle in enumerate(gl_entries):
+			self.assertEqual(expected_gle[i][0], gle.account)
+			self.assertEqual(expected_gle[i][1], gle.credit)
+			self.assertEqual(expected_gle[i][2], gle.debit)
+			self.assertEqual(getdate(expected_gle[i][3]), gle.posting_date)
+
+		acc_settings = frappe.get_doc('Accounts Settings', 'Accounts Settings')
+		acc_settings.book_deferred_entries_via_journal_entry = 0
+		acc_settings.submit_journal_entriessubmit_journal_entries = 0
+		acc_settings.save()
+
 
 def unlink_payment_on_cancel_of_invoice(enable=1):
 	accounts_settings = frappe.get_doc("Accounts Settings")
diff --git a/erpnext/accounts/doctype/sales_invoice/pos.py b/erpnext/accounts/doctype/sales_invoice/pos.py
deleted file mode 100755
index c49ac29..0000000
--- a/erpnext/accounts/doctype/sales_invoice/pos.py
+++ /dev/null
@@ -1,626 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-from __future__ import unicode_literals
-
-import json
-
-import frappe
-from erpnext.accounts.party import get_party_account_currency
-from erpnext.controllers.accounts_controller import get_taxes_and_charges
-from erpnext.setup.utils import get_exchange_rate
-from erpnext.stock.get_item_details import get_pos_profile
-from frappe import _
-from frappe.core.doctype.communication.email import make
-from frappe.utils import nowdate, cint
-
-from six import string_types, iteritems
-
-
-@frappe.whitelist()
-def get_pos_data():
-	doc = frappe.new_doc('Sales Invoice')
-	doc.is_pos = 1
-	pos_profile = get_pos_profile(doc.company) or {}
-	if not pos_profile:
-		frappe.throw(_("POS Profile is required to use Point-of-Sale"))
-
-	if not doc.company:
-		doc.company = pos_profile.get('company')
-
-	doc.update_stock = pos_profile.get('update_stock')
-
-	if pos_profile.get('name'):
-		pos_profile = frappe.get_doc('POS Profile', pos_profile.get('name'))
-		pos_profile.validate()
-
-	company_data = get_company_data(doc.company)
-	update_pos_profile_data(doc, pos_profile, company_data)
-	update_multi_mode_option(doc, pos_profile)
-	default_print_format = pos_profile.get('print_format') or "Point of Sale"
-	print_template = frappe.db.get_value('Print Format', default_print_format, 'html')
-	items_list = get_items_list(pos_profile, doc.company)
-	customers = get_customers_list(pos_profile)
-
-	doc.plc_conversion_rate = update_plc_conversion_rate(doc, pos_profile)
-
-	return {
-		'doc': doc,
-		'default_customer': pos_profile.get('customer'),
-		'items': items_list,
-		'item_groups': get_item_groups(pos_profile),
-		'customers': customers,
-		'address': get_customers_address(customers),
-		'contacts': get_contacts(customers),
-		'serial_no_data': get_serial_no_data(pos_profile, doc.company),
-		'batch_no_data': get_batch_no_data(),
-		'barcode_data': get_barcode_data(items_list),
-		'tax_data': get_item_tax_data(),
-		'price_list_data': get_price_list_data(doc.selling_price_list, doc.plc_conversion_rate),
-		'customer_wise_price_list': get_customer_wise_price_list(),
-		'bin_data': get_bin_data(pos_profile),
-		'pricing_rules': get_pricing_rule_data(doc),
-		'print_template': print_template,
-		'pos_profile': pos_profile,
-		'meta': get_meta()
-	}
-
-def update_plc_conversion_rate(doc, pos_profile):
-	conversion_rate = 1.0
-
-	price_list_currency = frappe.get_cached_value("Price List", doc.selling_price_list, "currency")
-	if pos_profile.get("currency") != price_list_currency:
-		conversion_rate = get_exchange_rate(price_list_currency,
-			pos_profile.get("currency"), nowdate(), args="for_selling") or 1.0
-
-	return conversion_rate
-
-def get_meta():
-	doctype_meta = {
-		'customer': frappe.get_meta('Customer'),
-		'invoice': frappe.get_meta('Sales Invoice')
-	}
-
-	for row in frappe.get_all('DocField', fields=['fieldname', 'options'],
-            filters={'parent': 'Sales Invoice', 'fieldtype': 'Table'}):
-		doctype_meta[row.fieldname] = frappe.get_meta(row.options)
-
-	return doctype_meta
-
-
-def get_company_data(company):
-	return frappe.get_all('Company', fields=["*"], filters={'name': company})[0]
-
-
-def update_pos_profile_data(doc, pos_profile, company_data):
-	doc.campaign = pos_profile.get('campaign')
-	if pos_profile and not pos_profile.get('country'):
-		pos_profile.country = company_data.country
-
-	doc.write_off_account = pos_profile.get('write_off_account') or \
-		company_data.write_off_account
-	doc.change_amount_account = pos_profile.get('change_amount_account') or \
-		company_data.default_cash_account
-	doc.taxes_and_charges = pos_profile.get('taxes_and_charges')
-	if doc.taxes_and_charges:
-		update_tax_table(doc)
-
-	doc.currency = pos_profile.get('currency') or company_data.default_currency
-	doc.conversion_rate = 1.0
-
-	if doc.currency != company_data.default_currency:
-		doc.conversion_rate = get_exchange_rate(doc.currency, company_data.default_currency, doc.posting_date, args="for_selling")
-
-	doc.selling_price_list = pos_profile.get('selling_price_list') or \
-		frappe.db.get_value('Selling Settings', None, 'selling_price_list')
-	doc.naming_series = pos_profile.get('naming_series') or 'SINV-'
-	doc.letter_head = pos_profile.get('letter_head') or company_data.default_letter_head
-	doc.ignore_pricing_rule = pos_profile.get('ignore_pricing_rule') or 0
-	doc.apply_discount_on = pos_profile.get('apply_discount_on') or 'Grand Total'
-	doc.customer_group = pos_profile.get('customer_group') or get_root('Customer Group')
-	doc.territory = pos_profile.get('territory') or get_root('Territory')
-	doc.terms = frappe.db.get_value('Terms and Conditions', pos_profile.get('tc_name'), 'terms') or doc.terms or ''
-	doc.offline_pos_name = ''
-
-
-def get_root(table):
-	root = frappe.db.sql(""" select name from `tab%(table)s` having
-		min(lft)""" % {'table': table}, as_dict=1)
-
-	return root[0].name
-
-
-def update_multi_mode_option(doc, pos_profile):
-	from frappe.model import default_fields
-
-	if not pos_profile or not pos_profile.get('payments'):
-		for payment in get_mode_of_payment(doc):
-			payments = doc.append('payments', {})
-			payments.mode_of_payment = payment.parent
-			payments.account = payment.default_account
-			payments.type = payment.type
-
-		return
-
-	for payment_mode in pos_profile.payments:
-		payment_mode = payment_mode.as_dict()
-
-		for fieldname in default_fields:
-			if fieldname in payment_mode:
-				del payment_mode[fieldname]
-
-		doc.append('payments', payment_mode)
-
-
-def get_mode_of_payment(doc):
-	return frappe.db.sql("""
-		select mpa.default_account, mpa.parent, mp.type as type 
-		from `tabMode of Payment Account` mpa,`tabMode of Payment` mp 
-		where mpa.parent = mp.name and mpa.company = %(company)s and mp.enabled = 1""",
-	{'company': doc.company}, as_dict=1)
-
-
-def update_tax_table(doc):
-	taxes = get_taxes_and_charges('Sales Taxes and Charges Template', doc.taxes_and_charges)
-	for tax in taxes:
-		doc.append('taxes', tax)
-
-
-def get_items_list(pos_profile, company):
-	cond = ""
-	args_list = []
-	if pos_profile.get('item_groups'):
-		# Get items based on the item groups defined in the POS profile
-		for d in pos_profile.get('item_groups'):
-			args_list.extend([d.name for d in get_child_nodes('Item Group', d.item_group)])
-		if args_list:
-			cond = "and i.item_group in (%s)" % (', '.join(['%s'] * len(args_list)))
-
-	return frappe.db.sql("""
-		select
-			i.name, i.item_code, i.item_name, i.description, i.item_group, i.has_batch_no,
-			i.has_serial_no, i.is_stock_item, i.brand, i.stock_uom, i.image,
-			id.expense_account, id.selling_cost_center, id.default_warehouse,
-			i.sales_uom, c.conversion_factor
-		from
-			`tabItem` i
-		left join `tabItem Default` id on id.parent = i.name and id.company = %s
-		left join `tabUOM Conversion Detail` c on i.name = c.parent and i.sales_uom = c.uom
-		where
-			i.disabled = 0 and i.has_variants = 0 and i.is_sales_item = 1
-			{cond}
-		""".format(cond=cond), tuple([company] + args_list), as_dict=1)
-
-
-def get_item_groups(pos_profile):
-	item_group_dict = {}
-	item_groups = frappe.db.sql("""Select name,
-		lft, rgt from `tabItem Group` order by lft""", as_dict=1)
-
-	for data in item_groups:
-		item_group_dict[data.name] = [data.lft, data.rgt]
-	return item_group_dict
-
-
-def get_customers_list(pos_profile={}):
-	cond = "1=1"
-	customer_groups = []
-	if pos_profile.get('customer_groups'):
-		# Get customers based on the customer groups defined in the POS profile
-		for d in pos_profile.get('customer_groups'):
-			customer_groups.extend([d.get('name') for d in get_child_nodes('Customer Group', d.get('customer_group'))])
-		cond = "customer_group in (%s)" % (', '.join(['%s'] * len(customer_groups)))
-
-	return frappe.db.sql(""" select name, customer_name, customer_group,
-		territory, customer_pos_id from tabCustomer where disabled = 0
-		and {cond}""".format(cond=cond), tuple(customer_groups), as_dict=1) or {}
-
-
-def get_customers_address(customers):
-	customer_address = {}
-	if isinstance(customers, string_types):
-		customers = [frappe._dict({'name': customers})]
-
-	for data in customers:
-		address = frappe.db.sql(""" select name, address_line1, address_line2, city, state,
-			email_id, phone, fax, pincode from `tabAddress` where is_primary_address =1 and name in
-			(select parent from `tabDynamic Link` where link_doctype = 'Customer' and link_name = %s
-			and parenttype = 'Address')""", data.name, as_dict=1)
-		address_data = {}
-		if address:
-			address_data = address[0]
-
-		address_data.update({'full_name': data.customer_name, 'customer_pos_id': data.customer_pos_id})
-		customer_address[data.name] = address_data
-
-	return customer_address
-
-
-def get_contacts(customers):
-	customer_contact = {}
-	if isinstance(customers, string_types):
-		customers = [frappe._dict({'name': customers})]
-
-	for data in customers:
-		contact = frappe.db.sql(""" select email_id, phone, mobile_no from `tabContact`
-			where is_primary_contact=1 and name in
-			(select parent from `tabDynamic Link` where link_doctype = 'Customer' and link_name = %s
-			and parenttype = 'Contact')""", data.name, as_dict=1)
-		if contact:
-			customer_contact[data.name] = contact[0]
-
-	return customer_contact
-
-
-def get_child_nodes(group_type, root):
-	lft, rgt = frappe.db.get_value(group_type, root, ["lft", "rgt"])
-	return frappe.db.sql(""" Select name, lft, rgt from `tab{tab}` where
-			lft >= {lft} and rgt <= {rgt} order by lft""".format(tab=group_type, lft=lft, rgt=rgt), as_dict=1)
-
-
-def get_serial_no_data(pos_profile, company):
-	# get itemwise serial no data
-	# example {'Nokia Lumia 1020': {'SN0001': 'Pune'}}
-	# where Nokia Lumia 1020 is item code, SN0001 is serial no and Pune is warehouse
-
-	cond = "1=1"
-	if pos_profile.get('update_stock') and pos_profile.get('warehouse'):
-		cond = "warehouse = %(warehouse)s"
-
-	serial_nos = frappe.db.sql("""select name, warehouse, item_code
-		from `tabSerial No` where {0} and company = %(company)s """.format(cond),{
-			'company': company, 'warehouse': frappe.db.escape(pos_profile.get('warehouse'))
-		}, as_dict=1)
-
-	itemwise_serial_no = {}
-	for sn in serial_nos:
-		if sn.item_code not in itemwise_serial_no:
-			itemwise_serial_no.setdefault(sn.item_code, {})
-		itemwise_serial_no[sn.item_code][sn.name] = sn.warehouse
-
-	return itemwise_serial_no
-
-
-def get_batch_no_data():
-	# get itemwise batch no data
-	# exmaple: {'LED-GRE': [Batch001, Batch002]}
-	# where LED-GRE is item code, SN0001 is serial no and Pune is warehouse
-
-	itemwise_batch = {}
-	batches = frappe.db.sql("""select name, item from `tabBatch`
-		where ifnull(expiry_date, '4000-10-10') >= curdate()""", as_dict=1)
-
-	for batch in batches:
-		if batch.item not in itemwise_batch:
-			itemwise_batch.setdefault(batch.item, [])
-		itemwise_batch[batch.item].append(batch.name)
-
-	return itemwise_batch
-
-
-def get_barcode_data(items_list):
-	# get itemwise batch no data
-	# exmaple: {'LED-GRE': [Batch001, Batch002]}
-	# where LED-GRE is item code, SN0001 is serial no and Pune is warehouse
-
-	itemwise_barcode = {}
-	for item in items_list:
-		barcodes = frappe.db.sql("""
-			select barcode from `tabItem Barcode` where parent = %s
-		""", item.item_code, as_dict=1)
-
-		for barcode in barcodes:
-			if item.item_code not in itemwise_barcode:
-				itemwise_barcode.setdefault(item.item_code, [])
-			itemwise_barcode[item.item_code].append(barcode.get("barcode"))
-
-	return itemwise_barcode
-
-
-def get_item_tax_data():
-	# get default tax of an item
-	# example: {'Consulting Services': {'Excise 12 - TS': '12.000'}}
-
-	itemwise_tax = {}
-	taxes = frappe.db.sql(""" select parent, tax_type, tax_rate from `tabItem Tax Template Detail`""", as_dict=1)
-
-	for tax in taxes:
-		if tax.parent not in itemwise_tax:
-			itemwise_tax.setdefault(tax.parent, {})
-		itemwise_tax[tax.parent][tax.tax_type] = tax.tax_rate
-
-	return itemwise_tax
-
-
-def get_price_list_data(selling_price_list, conversion_rate):
-	itemwise_price_list = {}
-	price_lists = frappe.db.sql("""Select ifnull(price_list_rate, 0) as price_list_rate,
-		item_code from `tabItem Price` ip where price_list = %(price_list)s""",
-        {'price_list': selling_price_list}, as_dict=1)
-
-	for item in price_lists:
-		itemwise_price_list[item.item_code] = item.price_list_rate * conversion_rate
-
-	return itemwise_price_list
-
-def get_customer_wise_price_list():
-	customer_wise_price = {}
-	customer_price_list_mapping = frappe._dict(frappe.get_all('Customer',fields = ['default_price_list', 'name'], as_list=1))
-
-	price_lists = frappe.db.sql(""" Select ifnull(price_list_rate, 0) as price_list_rate,
-		item_code, price_list from `tabItem Price` """, as_dict=1)
-
-	for item in price_lists:
-		if item.price_list and customer_price_list_mapping.get(item.price_list):
-
-			customer_wise_price.setdefault(customer_price_list_mapping.get(item.price_list),{}).setdefault(
-				item.item_code, item.price_list_rate
-			)
-
-	return customer_wise_price
-
-def get_bin_data(pos_profile):
-	itemwise_bin_data = {}
-	filters = { 'actual_qty': ['>', 0] }
-	if pos_profile.get('warehouse'):
-		filters.update({ 'warehouse': pos_profile.get('warehouse') })
-
-	bin_data = frappe.db.get_all('Bin', fields = ['item_code', 'warehouse', 'actual_qty'], filters=filters)
-
-	for bins in bin_data:
-		if bins.item_code not in itemwise_bin_data:
-			itemwise_bin_data.setdefault(bins.item_code, {})
-		itemwise_bin_data[bins.item_code][bins.warehouse] = bins.actual_qty
-
-	return itemwise_bin_data
-
-
-def get_pricing_rule_data(doc):
-	pricing_rules = ""
-	if doc.ignore_pricing_rule == 0:
-		pricing_rules = frappe.db.sql(""" Select * from `tabPricing Rule` where docstatus < 2
-						and ifnull(for_price_list, '') in (%(price_list)s, '') and selling = 1
-						and ifnull(company, '') in (%(company)s, '') and disable = 0 and %(date)s
-						between ifnull(valid_from, '2000-01-01') and ifnull(valid_upto, '2500-12-31')
-						order by priority desc, name desc""",
-                        {'company': doc.company, 'price_list': doc.selling_price_list, 'date': nowdate()}, as_dict=1)
-	return pricing_rules
-
-
-@frappe.whitelist()
-def make_invoice(pos_profile, doc_list={}, email_queue_list={}, customers_list={}):
-	import json
-
-	if isinstance(doc_list, string_types):
-		doc_list = json.loads(doc_list)
-
-	if isinstance(email_queue_list, string_types):
-		email_queue_list = json.loads(email_queue_list)
-
-	if isinstance(customers_list, string_types):
-		customers_list = json.loads(customers_list)
-
-	customers_list = make_customer_and_address(customers_list)
-	name_list = []
-	for docs in doc_list:
-		for name, doc in iteritems(docs):
-			if not frappe.db.exists('Sales Invoice', {'offline_pos_name': name}):
-				if isinstance(doc, dict):
-					validate_records(doc)
-					si_doc = frappe.new_doc('Sales Invoice')
-					si_doc.offline_pos_name = name
-					si_doc.update(doc)
-					si_doc.set_posting_time = 1
-					si_doc.customer = get_customer_id(doc)
-					si_doc.due_date = doc.get('posting_date')
-					name_list = submit_invoice(si_doc, name, doc, name_list)
-				else:
-					doc.due_date = doc.get('posting_date')
-					doc.customer = get_customer_id(doc)
-					doc.set_posting_time = 1
-					doc.offline_pos_name = name
-					name_list = submit_invoice(doc, name, doc, name_list)
-			else:
-				name_list.append(name)
-
-	email_queue = make_email_queue(email_queue_list)
-
-	if isinstance(pos_profile, string_types):
-		pos_profile = json.loads(pos_profile)
-
-	customers = get_customers_list(pos_profile)
-	return {
-		'invoice': name_list,
-		'email_queue': email_queue,
-		'customers': customers_list,
-		'synced_customers_list': customers,
-		'synced_address': get_customers_address(customers),
-		'synced_contacts': get_contacts(customers)
-	}
-
-
-def validate_records(doc):
-	validate_item(doc)
-
-
-def get_customer_id(doc, customer=None):
-	cust_id = None
-	if doc.get('customer_pos_id'):
-		cust_id = frappe.db.get_value('Customer',{'customer_pos_id': doc.get('customer_pos_id')}, 'name')
-
-	if not cust_id:
-		customer = customer or doc.get('customer')
-		if frappe.db.exists('Customer', customer):
-			cust_id = customer
-		else:
-			cust_id = add_customer(doc)
-
-	return cust_id
-
-def make_customer_and_address(customers):
-	customers_list = []
-	for customer, data in iteritems(customers):
-		data = json.loads(data)
-		cust_id = get_customer_id(data, customer)
-		if not cust_id:
-			cust_id = add_customer(data)
-		else:
-			frappe.db.set_value("Customer", cust_id, "customer_name", data.get('full_name'))
-
-		make_contact(data, cust_id)
-		make_address(data, cust_id)
-		customers_list.append(customer)
-	frappe.db.commit()
-	return customers_list
-
-def add_customer(data):
-	customer = data.get('full_name') or data.get('customer')
-	if frappe.db.exists("Customer", customer.strip()):
-		return customer.strip()
-
-	customer_doc = frappe.new_doc('Customer')
-	customer_doc.customer_name = data.get('full_name') or data.get('customer')
-	customer_doc.customer_pos_id = data.get('customer_pos_id')
-	customer_doc.customer_type = 'Company'
-	customer_doc.customer_group = get_customer_group(data)
-	customer_doc.territory = get_territory(data)
-	customer_doc.flags.ignore_mandatory = True
-	customer_doc.save(ignore_permissions=True)
-	frappe.db.commit()
-	return customer_doc.name
-
-def get_territory(data):
-	if data.get('territory'):
-		return data.get('territory')
-
-	return frappe.db.get_single_value('Selling Settings','territory') or _('All Territories')
-
-def get_customer_group(data):
-	if data.get('customer_group'):
-		return data.get('customer_group')
-
-	return frappe.db.get_single_value('Selling Settings', 'customer_group') or frappe.db.get_value('Customer Group', {'is_group': 0}, 'name')
-
-def make_contact(args, customer):
-	if args.get('email_id') or args.get('phone'):
-		name = frappe.db.get_value('Dynamic Link',
-            	{'link_doctype': 'Customer', 'link_name': customer, 'parenttype': 'Contact'}, 'parent')
-
-		args = {
-			'first_name': args.get('full_name'),
-			'email_id': args.get('email_id'),
-			'phone': args.get('phone')
-		}
-
-		doc = frappe.new_doc('Contact')
-		if name:
-			doc = frappe.get_doc('Contact', name)
-
-		doc.update(args)
-		doc.is_primary_contact = 1
-		if not name:
-			doc.append('links', {
-				'link_doctype': 'Customer',
-				'link_name': customer
-			})
-		doc.flags.ignore_mandatory = True
-		doc.save(ignore_permissions=True)
-
-def make_address(args, customer):
-	if not args.get('address_line1'):
-		return
-
-	name = args.get('name')
-
-	if not name:
-		data = get_customers_address(customer)
-		name = data[customer].get('name') if data else None
-
-	if name:
-		address = frappe.get_doc('Address', name)
-	else:
-		address = frappe.new_doc('Address')
-		if args.get('company'):
-			address.country = frappe.get_cached_value('Company',
-				args.get('company'),  'country')
-
-		address.append('links', {
-			'link_doctype': 'Customer',
-			'link_name': customer
-		})
-
-	address.is_primary_address = 1
-	address.is_shipping_address = 1
-	address.update(args)
-	address.flags.ignore_mandatory = True
-	address.save(ignore_permissions=True)
-
-def make_email_queue(email_queue):
-	name_list = []
-
-	for key, data in iteritems(email_queue):
-		name = frappe.db.get_value('Sales Invoice', {'offline_pos_name': key}, 'name')
-		if not name: continue
-
-		data = json.loads(data)
-		sender = frappe.session.user
-		print_format = "POS Invoice" if not cint(frappe.db.get_value('Print Format', 'POS Invoice', 'disabled')) else None
-
-		attachments = [frappe.attach_print('Sales Invoice', name, print_format=print_format)]
-
-		make(subject=data.get('subject'), content=data.get('content'), recipients=data.get('recipients'),
-                    sender=sender, attachments=attachments, send_email=True,
-                    doctype='Sales Invoice', name=name)
-		name_list.append(key)
-
-	return name_list
-
-def validate_item(doc):
-	for item in doc.get('items'):
-		if not frappe.db.exists('Item', item.get('item_code')):
-			item_doc = frappe.new_doc('Item')
-			item_doc.name = item.get('item_code')
-			item_doc.item_code = item.get('item_code')
-			item_doc.item_name = item.get('item_name')
-			item_doc.description = item.get('description')
-			item_doc.stock_uom = item.get('stock_uom')
-			item_doc.uom = item.get('uom')
-			item_doc.item_group = item.get('item_group')
-			item_doc.append('item_defaults', {
-				"company": doc.get("company"),
-				"default_warehouse": item.get('warehouse')
-			})
-			item_doc.save(ignore_permissions=True)
-			frappe.db.commit()
-
-def submit_invoice(si_doc, name, doc, name_list):
-	try:
-		si_doc.insert()
-		si_doc.submit()
-		frappe.db.commit()
-		name_list.append(name)
-	except Exception as e:
-		if frappe.message_log:
-			frappe.message_log.pop()
-		frappe.db.rollback()
-		frappe.log_error(frappe.get_traceback())
-		name_list = save_invoice(doc, name, name_list)
-
-	return name_list
-
-def save_invoice(doc, name, name_list):
-	try:
-		if not frappe.db.exists('Sales Invoice', {'offline_pos_name': name}):
-			si = frappe.new_doc('Sales Invoice')
-			si.update(doc)
-			si.set_posting_time = 1
-			si.customer = get_customer_id(doc)
-			si.due_date = doc.get('posting_date')
-			si.flags.ignore_mandatory = True
-			si.insert(ignore_permissions=True)
-			frappe.db.commit()
-			name_list.append(name)
-	except Exception:
-		frappe.db.rollback()
-		frappe.log_error(frappe.get_traceback())
-
-	return name_list
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
index df0c3d2..9af584e 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
@@ -96,6 +96,12 @@
 				cur_frm.add_custom_button(__('Invoice Discounting'), function() {
 					cur_frm.events.create_invoice_discounting(cur_frm);
 				}, __('Create'));
+
+				if (doc.due_date < frappe.datetime.get_today()) {
+					cur_frm.add_custom_button(__('Dunning'), function() {
+						cur_frm.events.create_dunning(cur_frm);
+					}, __('Create'));
+				}
 			}
 
 			if (doc.docstatus === 1) {
@@ -276,7 +282,7 @@
 					"customer": this.frm.doc.customer
 				},
 				callback: function(r) {
-					if(r.message && r.message.length) {
+					if(r.message && r.message.length > 1) {
 						select_loyalty_program(me.frm, r.message);
 					}
 				}
@@ -824,6 +830,12 @@
 			method: "erpnext.accounts.doctype.sales_invoice.sales_invoice.create_invoice_discounting",
 			frm: frm
 		});
+	},
+	create_dunning: function(frm) {
+		frappe.model.open_mapped_doc({
+			method: "erpnext.accounts.doctype.sales_invoice.sales_invoice.create_dunning",
+			frm: frm
+		});
 	}
 })
 
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json
index 63c34ed..4dc81e9 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json
@@ -1,6 +1,7 @@
 {
  "actions": [],
  "allow_import": 1,
+ "allow_workflow": 1,
  "autoname": "naming_series:",
  "creation": "2013-05-24 19:29:05",
  "doctype": "DocType",
@@ -13,6 +14,7 @@
   "customer_name",
   "tax_id",
   "is_pos",
+  "is_consolidated",
   "pos_profile",
   "offline_pos_name",
   "is_return",
@@ -189,6 +191,8 @@
   {
    "fieldname": "customer_section",
    "fieldtype": "Section Break",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "options": "fa fa-user"
   },
   {
@@ -197,6 +201,8 @@
    "fieldname": "title",
    "fieldtype": "Data",
    "hidden": 1,
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Title",
    "no_copy": 1,
    "print_hide": 1
@@ -205,6 +211,8 @@
    "bold": 1,
    "fieldname": "naming_series",
    "fieldtype": "Select",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Series",
    "no_copy": 1,
    "oldfieldname": "naming_series",
@@ -218,6 +226,8 @@
    "bold": 1,
    "fieldname": "customer",
    "fieldtype": "Link",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "in_standard_filter": 1,
    "label": "Customer",
    "oldfieldname": "customer",
@@ -232,6 +242,8 @@
    "fetch_from": "customer.customer_name",
    "fieldname": "customer_name",
    "fieldtype": "Data",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "in_global_search": 1,
    "label": "Customer Name",
    "oldfieldname": "customer_name",
@@ -241,6 +253,8 @@
   {
    "fieldname": "tax_id",
    "fieldtype": "Data",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Tax Id",
    "print_hide": 1,
    "read_only": 1
@@ -248,6 +262,8 @@
   {
    "fieldname": "project",
    "fieldtype": "Link",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "in_global_search": 1,
    "label": "Project",
    "oldfieldname": "project_name",
@@ -259,6 +275,8 @@
    "default": "0",
    "fieldname": "is_pos",
    "fieldtype": "Check",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Include Payment (POS)",
    "oldfieldname": "is_pos",
    "oldfieldtype": "Check",
@@ -268,6 +286,8 @@
    "depends_on": "is_pos",
    "fieldname": "pos_profile",
    "fieldtype": "Link",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "POS Profile",
    "options": "POS Profile",
    "print_hide": 1
@@ -276,6 +296,8 @@
    "fieldname": "offline_pos_name",
    "fieldtype": "Data",
    "hidden": 1,
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Offline POS Name",
    "print_hide": 1,
    "read_only": 1
@@ -284,6 +306,8 @@
    "default": "0",
    "fieldname": "is_return",
    "fieldtype": "Check",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Is Return (Credit Note)",
    "no_copy": 1,
    "print_hide": 1
@@ -291,11 +315,15 @@
   {
    "fieldname": "column_break1",
    "fieldtype": "Column Break",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "oldfieldtype": "Column Break"
   },
   {
    "fieldname": "company",
    "fieldtype": "Link",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "in_standard_filter": 1,
    "label": "Company",
    "oldfieldname": "company",
@@ -308,6 +336,8 @@
   {
    "fieldname": "cost_center",
    "fieldtype": "Link",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Cost Center",
    "options": "Cost Center"
   },
@@ -316,6 +346,8 @@
    "default": "Today",
    "fieldname": "posting_date",
    "fieldtype": "Date",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Date",
    "no_copy": 1,
    "oldfieldname": "posting_date",
@@ -326,6 +358,8 @@
   {
    "fieldname": "posting_time",
    "fieldtype": "Time",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Posting Time",
    "no_copy": 1,
    "oldfieldname": "posting_time",
@@ -337,12 +371,16 @@
    "depends_on": "eval:doc.docstatus==0",
    "fieldname": "set_posting_time",
    "fieldtype": "Check",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Edit Posting Date and Time",
    "print_hide": 1
   },
   {
    "fieldname": "due_date",
    "fieldtype": "Date",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Payment Due Date",
    "no_copy": 1,
    "oldfieldname": "due_date",
@@ -351,6 +389,8 @@
   {
    "fieldname": "amended_from",
    "fieldtype": "Link",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "ignore_user_permissions": 1,
    "label": "Amended From",
    "no_copy": 1,
@@ -364,12 +404,16 @@
    "depends_on": "return_against",
    "fieldname": "returns",
    "fieldtype": "Section Break",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Returns"
   },
   {
    "depends_on": "return_against",
    "fieldname": "return_against",
    "fieldtype": "Link",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Return Against Sales Invoice",
    "no_copy": 1,
    "options": "Sales Invoice",
@@ -379,13 +423,17 @@
   },
   {
    "fieldname": "column_break_21",
-   "fieldtype": "Column Break"
+   "fieldtype": "Column Break",
+   "hide_days": 1,
+   "hide_seconds": 1
   },
   {
    "default": "0",
    "depends_on": "eval: doc.is_return && doc.return_against",
    "fieldname": "update_billed_amount_in_sales_order",
    "fieldtype": "Check",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Update Billed Amount in Sales Order"
   },
   {
@@ -393,35 +441,47 @@
    "collapsible_depends_on": "po_no",
    "fieldname": "customer_po_details",
    "fieldtype": "Section Break",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Customer PO Details"
   },
   {
    "allow_on_submit": 1,
    "fieldname": "po_no",
    "fieldtype": "Small Text",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Customer's Purchase Order",
    "no_copy": 1,
    "print_hide": 1
   },
   {
    "fieldname": "column_break_23",
-   "fieldtype": "Column Break"
+   "fieldtype": "Column Break",
+   "hide_days": 1,
+   "hide_seconds": 1
   },
   {
    "allow_on_submit": 1,
    "fieldname": "po_date",
    "fieldtype": "Date",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Customer's Purchase Order Date"
   },
   {
    "collapsible": 1,
    "fieldname": "address_and_contact",
    "fieldtype": "Section Break",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Address and Contact"
   },
   {
    "fieldname": "customer_address",
    "fieldtype": "Link",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Customer Address",
    "options": "Address",
    "print_hide": 1
@@ -429,12 +489,16 @@
   {
    "fieldname": "address_display",
    "fieldtype": "Small Text",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Address",
    "read_only": 1
   },
   {
    "fieldname": "contact_person",
    "fieldtype": "Link",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "in_global_search": 1,
    "label": "Contact Person",
    "options": "Contact",
@@ -443,6 +507,8 @@
   {
    "fieldname": "contact_display",
    "fieldtype": "Small Text",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Contact",
    "read_only": 1
   },
@@ -450,6 +516,8 @@
    "fieldname": "contact_mobile",
    "fieldtype": "Small Text",
    "hidden": 1,
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Mobile No",
    "read_only": 1
   },
@@ -457,6 +525,8 @@
    "fieldname": "contact_email",
    "fieldtype": "Data",
    "hidden": 1,
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Contact Email",
    "options": "Email",
    "print_hide": 1,
@@ -465,17 +535,23 @@
   {
    "fieldname": "territory",
    "fieldtype": "Link",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Territory",
    "options": "Territory",
    "print_hide": 1
   },
   {
    "fieldname": "col_break4",
-   "fieldtype": "Column Break"
+   "fieldtype": "Column Break",
+   "hide_days": 1,
+   "hide_seconds": 1
   },
   {
    "fieldname": "shipping_address_name",
    "fieldtype": "Link",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Shipping Address Name",
    "options": "Address",
    "print_hide": 1
@@ -483,6 +559,8 @@
   {
    "fieldname": "shipping_address",
    "fieldtype": "Small Text",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Shipping Address",
    "print_hide": 1,
    "read_only": 1
@@ -490,6 +568,8 @@
   {
    "fieldname": "company_address",
    "fieldtype": "Link",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Company Address Name",
    "options": "Address",
    "print_hide": 1
@@ -498,6 +578,8 @@
    "fieldname": "company_address_display",
    "fieldtype": "Small Text",
    "hidden": 1,
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Company Address",
    "print_hide": 1,
    "read_only": 1
@@ -507,11 +589,15 @@
    "depends_on": "customer",
    "fieldname": "currency_and_price_list",
    "fieldtype": "Section Break",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Currency and Price List"
   },
   {
    "fieldname": "currency",
    "fieldtype": "Link",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Currency",
    "oldfieldname": "currency",
    "oldfieldtype": "Select",
@@ -523,6 +609,8 @@
    "description": "Rate at which Customer Currency is converted to customer's base currency",
    "fieldname": "conversion_rate",
    "fieldtype": "Float",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Exchange Rate",
    "oldfieldname": "conversion_rate",
    "oldfieldtype": "Currency",
@@ -533,11 +621,15 @@
   {
    "fieldname": "column_break2",
    "fieldtype": "Column Break",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "width": "50%"
   },
   {
    "fieldname": "selling_price_list",
    "fieldtype": "Link",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Price List",
    "oldfieldname": "price_list_name",
    "oldfieldtype": "Select",
@@ -548,6 +640,8 @@
   {
    "fieldname": "price_list_currency",
    "fieldtype": "Link",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Price List Currency",
    "options": "Currency",
    "print_hide": 1,
@@ -558,6 +652,8 @@
    "description": "Rate at which Price list currency is converted to customer's base currency",
    "fieldname": "plc_conversion_rate",
    "fieldtype": "Float",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Price List Exchange Rate",
    "precision": "9",
    "print_hide": 1,
@@ -567,6 +663,8 @@
    "default": "0",
    "fieldname": "ignore_pricing_rule",
    "fieldtype": "Check",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Ignore Pricing Rule",
    "no_copy": 1,
    "permlevel": 1,
@@ -574,12 +672,16 @@
   },
   {
    "fieldname": "sec_warehouse",
-   "fieldtype": "Section Break"
+   "fieldtype": "Section Break",
+   "hide_days": 1,
+   "hide_seconds": 1
   },
   {
    "depends_on": "update_stock",
    "fieldname": "set_warehouse",
    "fieldtype": "Link",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Set Source Warehouse",
    "options": "Warehouse",
    "print_hide": 1
@@ -587,6 +689,8 @@
   {
    "fieldname": "items_section",
    "fieldtype": "Section Break",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "oldfieldtype": "Section Break",
    "options": "fa fa-shopping-cart"
   },
@@ -594,6 +698,8 @@
    "default": "0",
    "fieldname": "update_stock",
    "fieldtype": "Check",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Update Stock",
    "oldfieldname": "update_stock",
    "oldfieldtype": "Check",
@@ -602,12 +708,16 @@
   {
    "fieldname": "scan_barcode",
    "fieldtype": "Data",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Scan Barcode"
   },
   {
    "allow_bulk_edit": 1,
    "fieldname": "items",
    "fieldtype": "Table",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Items",
    "oldfieldname": "entries",
    "oldfieldtype": "Table",
@@ -617,11 +727,15 @@
   {
    "fieldname": "pricing_rule_details",
    "fieldtype": "Section Break",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Pricing Rules"
   },
   {
    "fieldname": "pricing_rules",
    "fieldtype": "Table",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Pricing Rule Detail",
    "options": "Pricing Rule Detail",
    "read_only": 1
@@ -629,6 +743,8 @@
   {
    "fieldname": "packing_list",
    "fieldtype": "Section Break",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Packing List",
    "options": "fa fa-suitcase",
    "print_hide": 1
@@ -636,6 +752,8 @@
   {
    "fieldname": "packed_items",
    "fieldtype": "Table",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Packed Items",
    "options": "Packed Item",
    "print_hide": 1
@@ -643,6 +761,8 @@
   {
    "fieldname": "product_bundle_help",
    "fieldtype": "HTML",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Product Bundle Help",
    "print_hide": 1
   },
@@ -651,11 +771,15 @@
    "collapsible_depends_on": "eval:doc.total_billing_amount > 0",
    "fieldname": "time_sheet_list",
    "fieldtype": "Section Break",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Time Sheet List"
   },
   {
    "fieldname": "timesheets",
    "fieldtype": "Table",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Time Sheets",
    "options": "Sales Invoice Timesheet",
    "print_hide": 1
@@ -664,23 +788,31 @@
    "default": "0",
    "fieldname": "total_billing_amount",
    "fieldtype": "Currency",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Total Billing Amount",
    "print_hide": 1,
    "read_only": 1
   },
   {
    "fieldname": "section_break_30",
-   "fieldtype": "Section Break"
+   "fieldtype": "Section Break",
+   "hide_days": 1,
+   "hide_seconds": 1
   },
   {
    "fieldname": "total_qty",
    "fieldtype": "Float",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Total Quantity",
    "read_only": 1
   },
   {
    "fieldname": "base_total",
    "fieldtype": "Currency",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Total (Company Currency)",
    "options": "Company:company:default_currency",
    "print_hide": 1,
@@ -689,6 +821,8 @@
   {
    "fieldname": "base_net_total",
    "fieldtype": "Currency",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Net Total (Company Currency)",
    "oldfieldname": "net_total",
    "oldfieldtype": "Currency",
@@ -699,11 +833,15 @@
   },
   {
    "fieldname": "column_break_32",
-   "fieldtype": "Column Break"
+   "fieldtype": "Column Break",
+   "hide_days": 1,
+   "hide_seconds": 1
   },
   {
    "fieldname": "total",
    "fieldtype": "Currency",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Total",
    "options": "currency",
    "read_only": 1
@@ -711,6 +849,8 @@
   {
    "fieldname": "net_total",
    "fieldtype": "Currency",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Net Total",
    "options": "currency",
    "print_hide": 1,
@@ -719,6 +859,8 @@
   {
    "fieldname": "total_net_weight",
    "fieldtype": "Float",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Total Net Weight",
    "print_hide": 1,
    "read_only": 1
@@ -726,12 +868,16 @@
   {
    "fieldname": "taxes_section",
    "fieldtype": "Section Break",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "oldfieldtype": "Section Break",
    "options": "fa fa-money"
   },
   {
    "fieldname": "taxes_and_charges",
    "fieldtype": "Link",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Sales Taxes and Charges Template",
    "oldfieldname": "charge",
    "oldfieldtype": "Link",
@@ -740,11 +886,15 @@
   },
   {
    "fieldname": "column_break_38",
-   "fieldtype": "Column Break"
+   "fieldtype": "Column Break",
+   "hide_days": 1,
+   "hide_seconds": 1
   },
   {
    "fieldname": "shipping_rule",
    "fieldtype": "Link",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Shipping Rule",
    "oldfieldtype": "Button",
    "options": "Shipping Rule",
@@ -753,17 +903,23 @@
   {
    "fieldname": "tax_category",
    "fieldtype": "Link",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Tax Category",
    "options": "Tax Category",
    "print_hide": 1
   },
   {
    "fieldname": "section_break_40",
-   "fieldtype": "Section Break"
+   "fieldtype": "Section Break",
+   "hide_days": 1,
+   "hide_seconds": 1
   },
   {
    "fieldname": "taxes",
    "fieldtype": "Table",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Sales Taxes and Charges",
    "oldfieldname": "other_charges",
    "oldfieldtype": "Table",
@@ -773,11 +929,15 @@
    "collapsible": 1,
    "fieldname": "sec_tax_breakup",
    "fieldtype": "Section Break",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Tax Breakup"
   },
   {
    "fieldname": "other_charges_calculation",
    "fieldtype": "Long Text",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Taxes and Charges Calculation",
    "no_copy": 1,
    "oldfieldtype": "HTML",
@@ -786,11 +946,15 @@
   },
   {
    "fieldname": "section_break_43",
-   "fieldtype": "Section Break"
+   "fieldtype": "Section Break",
+   "hide_days": 1,
+   "hide_seconds": 1
   },
   {
    "fieldname": "base_total_taxes_and_charges",
    "fieldtype": "Currency",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Total Taxes and Charges (Company Currency)",
    "oldfieldname": "other_charges_total",
    "oldfieldtype": "Currency",
@@ -800,11 +964,15 @@
   },
   {
    "fieldname": "column_break_47",
-   "fieldtype": "Column Break"
+   "fieldtype": "Column Break",
+   "hide_days": 1,
+   "hide_seconds": 1
   },
   {
    "fieldname": "total_taxes_and_charges",
    "fieldtype": "Currency",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Total Taxes and Charges",
    "options": "currency",
    "print_hide": 1,
@@ -814,12 +982,16 @@
    "collapsible": 1,
    "fieldname": "loyalty_points_redemption",
    "fieldtype": "Section Break",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Loyalty Points Redemption"
   },
   {
    "depends_on": "redeem_loyalty_points",
    "fieldname": "loyalty_points",
    "fieldtype": "Int",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Loyalty Points",
    "no_copy": 1,
    "print_hide": 1
@@ -828,6 +1000,8 @@
    "depends_on": "redeem_loyalty_points",
    "fieldname": "loyalty_amount",
    "fieldtype": "Currency",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Loyalty Amount",
    "no_copy": 1,
    "options": "Company:company:default_currency",
@@ -838,18 +1012,24 @@
    "default": "0",
    "fieldname": "redeem_loyalty_points",
    "fieldtype": "Check",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Redeem Loyalty Points",
    "no_copy": 1,
    "print_hide": 1
   },
   {
    "fieldname": "column_break_77",
-   "fieldtype": "Column Break"
+   "fieldtype": "Column Break",
+   "hide_days": 1,
+   "hide_seconds": 1
   },
   {
    "fetch_from": "customer.loyalty_program",
    "fieldname": "loyalty_program",
    "fieldtype": "Link",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Loyalty Program",
    "no_copy": 1,
    "options": "Loyalty Program",
@@ -860,6 +1040,8 @@
    "depends_on": "redeem_loyalty_points",
    "fieldname": "loyalty_redemption_account",
    "fieldtype": "Link",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Redemption Account",
    "no_copy": 1,
    "options": "Account"
@@ -868,6 +1050,8 @@
    "depends_on": "redeem_loyalty_points",
    "fieldname": "loyalty_redemption_cost_center",
    "fieldtype": "Link",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Redemption Cost Center",
    "no_copy": 1,
    "options": "Cost Center"
@@ -877,12 +1061,16 @@
    "collapsible_depends_on": "discount_amount",
    "fieldname": "section_break_49",
    "fieldtype": "Section Break",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Additional Discount"
   },
   {
    "default": "Grand Total",
    "fieldname": "apply_discount_on",
    "fieldtype": "Select",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Apply Additional Discount On",
    "options": "\nGrand Total\nNet Total",
    "print_hide": 1
@@ -890,6 +1078,8 @@
   {
    "fieldname": "base_discount_amount",
    "fieldtype": "Currency",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Additional Discount Amount (Company Currency)",
    "options": "Company:company:default_currency",
    "print_hide": 1,
@@ -897,17 +1087,23 @@
   },
   {
    "fieldname": "column_break_51",
-   "fieldtype": "Column Break"
+   "fieldtype": "Column Break",
+   "hide_days": 1,
+   "hide_seconds": 1
   },
   {
    "fieldname": "additional_discount_percentage",
    "fieldtype": "Float",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Additional Discount Percentage",
    "print_hide": 1
   },
   {
    "fieldname": "discount_amount",
    "fieldtype": "Currency",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Additional Discount Amount",
    "options": "currency",
    "print_hide": 1
@@ -915,6 +1111,8 @@
   {
    "fieldname": "totals",
    "fieldtype": "Section Break",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "oldfieldtype": "Section Break",
    "options": "fa fa-money",
    "print_hide": 1
@@ -922,6 +1120,8 @@
   {
    "fieldname": "base_grand_total",
    "fieldtype": "Currency",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Grand Total (Company Currency)",
    "oldfieldname": "grand_total",
    "oldfieldtype": "Currency",
@@ -933,6 +1133,8 @@
   {
    "fieldname": "base_rounding_adjustment",
    "fieldtype": "Currency",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Rounding Adjustment (Company Currency)",
    "no_copy": 1,
    "options": "Company:company:default_currency",
@@ -942,6 +1144,8 @@
   {
    "fieldname": "base_rounded_total",
    "fieldtype": "Currency",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Rounded Total (Company Currency)",
    "oldfieldname": "rounded_total",
    "oldfieldtype": "Currency",
@@ -953,7 +1157,10 @@
    "description": "In Words will be visible once you save the Sales Invoice.",
    "fieldname": "base_in_words",
    "fieldtype": "Data",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "In Words (Company Currency)",
+   "length": 240,
    "oldfieldname": "in_words",
    "oldfieldtype": "Data",
    "print_hide": 1,
@@ -962,6 +1169,8 @@
   {
    "fieldname": "column_break5",
    "fieldtype": "Column Break",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "oldfieldtype": "Column Break",
    "print_hide": 1,
    "width": "50%"
@@ -970,6 +1179,8 @@
    "bold": 1,
    "fieldname": "grand_total",
    "fieldtype": "Currency",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "in_list_view": 1,
    "label": "Grand Total",
    "oldfieldname": "grand_total_export",
@@ -981,6 +1192,8 @@
   {
    "fieldname": "rounding_adjustment",
    "fieldtype": "Currency",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Rounding Adjustment",
    "no_copy": 1,
    "options": "currency",
@@ -991,6 +1204,8 @@
    "bold": 1,
    "fieldname": "rounded_total",
    "fieldtype": "Currency",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Rounded Total",
    "oldfieldname": "rounded_total_export",
    "oldfieldtype": "Currency",
@@ -1000,7 +1215,10 @@
   {
    "fieldname": "in_words",
    "fieldtype": "Data",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "In Words",
+   "length": 240,
    "oldfieldname": "in_words_export",
    "oldfieldtype": "Data",
    "print_hide": 1,
@@ -1009,6 +1227,8 @@
   {
    "fieldname": "total_advance",
    "fieldtype": "Currency",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Total Advance",
    "oldfieldname": "total_advance",
    "oldfieldtype": "Currency",
@@ -1019,6 +1239,8 @@
   {
    "fieldname": "outstanding_amount",
    "fieldtype": "Currency",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Outstanding Amount",
    "no_copy": 1,
    "oldfieldname": "outstanding_amount",
@@ -1032,6 +1254,8 @@
    "collapsible_depends_on": "advances",
    "fieldname": "advances_section",
    "fieldtype": "Section Break",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Advance Payments",
    "oldfieldtype": "Section Break",
    "options": "fa fa-money",
@@ -1041,18 +1265,24 @@
    "default": "0",
    "fieldname": "allocate_advances_automatically",
    "fieldtype": "Check",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Allocate Advances Automatically (FIFO)"
   },
   {
    "depends_on": "eval:!doc.allocate_advances_automatically",
    "fieldname": "get_advances",
    "fieldtype": "Button",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Get Advances Received",
    "options": "set_advances"
   },
   {
    "fieldname": "advances",
    "fieldtype": "Table",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Advances",
    "oldfieldname": "advance_adjustment_details",
    "oldfieldtype": "Table",
@@ -1064,12 +1294,16 @@
    "collapsible_depends_on": "eval:(!doc.is_pos && !doc.is_return)",
    "fieldname": "payment_schedule_section",
    "fieldtype": "Section Break",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Payment Terms"
   },
   {
    "depends_on": "eval:(!doc.is_pos && !doc.is_return)",
    "fieldname": "payment_terms_template",
    "fieldtype": "Link",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Payment Terms Template",
    "no_copy": 1,
    "options": "Payment Terms Template",
@@ -1079,6 +1313,8 @@
    "depends_on": "eval:(!doc.is_pos && !doc.is_return)",
    "fieldname": "payment_schedule",
    "fieldtype": "Table",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Payment Schedule",
    "no_copy": 1,
    "options": "Payment Schedule",
@@ -1088,6 +1324,8 @@
    "depends_on": "eval:doc.is_pos===1||(doc.advances && doc.advances.length>0)",
    "fieldname": "payments_section",
    "fieldtype": "Section Break",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Payments",
    "options": "fa fa-money"
   },
@@ -1096,6 +1334,8 @@
    "fieldname": "cash_bank_account",
    "fieldtype": "Link",
    "hidden": 1,
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Cash/Bank Account",
    "oldfieldname": "cash_bank_account",
    "oldfieldtype": "Link",
@@ -1106,17 +1346,23 @@
    "depends_on": "eval:doc.is_pos===1",
    "fieldname": "payments",
    "fieldtype": "Table",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Sales Invoice Payment",
    "options": "Sales Invoice Payment",
    "print_hide": 1
   },
   {
    "fieldname": "section_break_84",
-   "fieldtype": "Section Break"
+   "fieldtype": "Section Break",
+   "hide_days": 1,
+   "hide_seconds": 1
   },
   {
    "fieldname": "base_paid_amount",
    "fieldtype": "Currency",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Paid Amount (Company Currency)",
    "no_copy": 1,
    "options": "Company:company:default_currency",
@@ -1125,12 +1371,16 @@
   },
   {
    "fieldname": "column_break_86",
-   "fieldtype": "Column Break"
+   "fieldtype": "Column Break",
+   "hide_days": 1,
+   "hide_seconds": 1
   },
   {
    "depends_on": "eval: doc.is_pos || doc.redeem_loyalty_points",
    "fieldname": "paid_amount",
    "fieldtype": "Currency",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Paid Amount",
    "no_copy": 1,
    "oldfieldname": "paid_amount",
@@ -1141,12 +1391,16 @@
   },
   {
    "fieldname": "section_break_88",
-   "fieldtype": "Section Break"
+   "fieldtype": "Section Break",
+   "hide_days": 1,
+   "hide_seconds": 1
   },
   {
    "depends_on": "is_pos",
    "fieldname": "base_change_amount",
    "fieldtype": "Currency",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Base Change Amount (Company Currency)",
    "no_copy": 1,
    "options": "Company:company:default_currency",
@@ -1155,12 +1409,16 @@
   },
   {
    "fieldname": "column_break_90",
-   "fieldtype": "Column Break"
+   "fieldtype": "Column Break",
+   "hide_days": 1,
+   "hide_seconds": 1
   },
   {
    "depends_on": "is_pos",
    "fieldname": "change_amount",
    "fieldtype": "Currency",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Change Amount",
    "no_copy": 1,
    "options": "currency",
@@ -1170,6 +1428,8 @@
    "depends_on": "is_pos",
    "fieldname": "account_for_change_amount",
    "fieldtype": "Link",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Account for Change Amount",
    "options": "Account",
    "print_hide": 1
@@ -1180,12 +1440,16 @@
    "depends_on": "grand_total",
    "fieldname": "column_break4",
    "fieldtype": "Section Break",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Write Off",
    "width": "50%"
   },
   {
    "fieldname": "write_off_amount",
    "fieldtype": "Currency",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Write Off Amount",
    "no_copy": 1,
    "options": "currency",
@@ -1194,6 +1458,8 @@
   {
    "fieldname": "base_write_off_amount",
    "fieldtype": "Currency",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Write Off Amount (Company Currency)",
    "no_copy": 1,
    "options": "Company:company:default_currency",
@@ -1205,16 +1471,22 @@
    "depends_on": "is_pos",
    "fieldname": "write_off_outstanding_amount_automatically",
    "fieldtype": "Check",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Write Off Outstanding Amount",
    "print_hide": 1
   },
   {
    "fieldname": "column_break_74",
-   "fieldtype": "Column Break"
+   "fieldtype": "Column Break",
+   "hide_days": 1,
+   "hide_seconds": 1
   },
   {
    "fieldname": "write_off_account",
    "fieldtype": "Link",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Write Off Account",
    "options": "Account",
    "print_hide": 1
@@ -1222,6 +1494,8 @@
   {
    "fieldname": "write_off_cost_center",
    "fieldtype": "Link",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Write Off Cost Center",
    "options": "Cost Center",
    "print_hide": 1
@@ -1231,12 +1505,16 @@
    "collapsible_depends_on": "terms",
    "fieldname": "terms_section_break",
    "fieldtype": "Section Break",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Terms and Conditions",
    "oldfieldtype": "Section Break"
   },
   {
    "fieldname": "tc_name",
    "fieldtype": "Link",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Terms",
    "oldfieldname": "tc_name",
    "oldfieldtype": "Link",
@@ -1246,6 +1524,8 @@
   {
    "fieldname": "terms",
    "fieldtype": "Text Editor",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Terms and Conditions Details",
    "oldfieldname": "terms",
    "oldfieldtype": "Text Editor"
@@ -1254,12 +1534,16 @@
    "collapsible": 1,
    "fieldname": "edit_printing_settings",
    "fieldtype": "Section Break",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Printing Settings"
   },
   {
    "allow_on_submit": 1,
    "fieldname": "letter_head",
    "fieldtype": "Link",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Letter Head",
    "oldfieldname": "letter_head",
    "oldfieldtype": "Select",
@@ -1271,24 +1555,32 @@
    "default": "0",
    "fieldname": "group_same_items",
    "fieldtype": "Check",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Group same items",
    "print_hide": 1
   },
   {
    "fieldname": "language",
    "fieldtype": "Data",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Print Language",
    "print_hide": 1,
    "read_only": 1
   },
   {
    "fieldname": "column_break_84",
-   "fieldtype": "Column Break"
+   "fieldtype": "Column Break",
+   "hide_days": 1,
+   "hide_seconds": 1
   },
   {
    "allow_on_submit": 1,
    "fieldname": "select_print_heading",
    "fieldtype": "Link",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Print Heading",
    "no_copy": 1,
    "oldfieldname": "select_print_heading",
@@ -1302,11 +1594,15 @@
    "depends_on": "customer",
    "fieldname": "more_information",
    "fieldtype": "Section Break",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "More Information"
   },
   {
    "fieldname": "inter_company_invoice_reference",
    "fieldtype": "Link",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Inter Company Invoice Reference",
    "options": "Purchase Invoice",
    "read_only": 1
@@ -1315,6 +1611,8 @@
    "fieldname": "customer_group",
    "fieldtype": "Link",
    "hidden": 1,
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Customer Group",
    "options": "Customer Group",
    "print_hide": 1
@@ -1322,6 +1620,8 @@
   {
    "fieldname": "campaign",
    "fieldtype": "Link",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Campaign",
    "oldfieldname": "campaign",
    "oldfieldtype": "Link",
@@ -1332,6 +1632,8 @@
    "default": "0",
    "fieldname": "is_discounted",
    "fieldtype": "Check",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Is Discounted",
    "no_copy": 1,
    "read_only": 1
@@ -1339,12 +1641,16 @@
   {
    "fieldname": "col_break23",
    "fieldtype": "Column Break",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "width": "50%"
   },
   {
    "default": "Draft",
    "fieldname": "status",
    "fieldtype": "Select",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "in_standard_filter": 1,
    "label": "Status",
    "no_copy": 1,
@@ -1355,6 +1661,8 @@
   {
    "fieldname": "source",
    "fieldtype": "Link",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Source",
    "oldfieldname": "source",
    "oldfieldtype": "Select",
@@ -1365,6 +1673,8 @@
    "collapsible": 1,
    "fieldname": "more_info",
    "fieldtype": "Section Break",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Accounting Details",
    "oldfieldtype": "Section Break",
    "options": "fa fa-file-text",
@@ -1373,6 +1683,8 @@
   {
    "fieldname": "debit_to",
    "fieldtype": "Link",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Debit To",
    "oldfieldname": "debit_to",
    "oldfieldtype": "Link",
@@ -1385,6 +1697,8 @@
    "fieldname": "party_account_currency",
    "fieldtype": "Link",
    "hidden": 1,
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Party Account Currency",
    "no_copy": 1,
    "options": "Currency",
@@ -1395,6 +1709,8 @@
    "default": "No",
    "fieldname": "is_opening",
    "fieldtype": "Select",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Is Opening Entry",
    "oldfieldname": "is_opening",
    "oldfieldtype": "Select",
@@ -1404,6 +1720,8 @@
   {
    "fieldname": "c_form_applicable",
    "fieldtype": "Select",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "C-Form Applicable",
    "no_copy": 1,
    "options": "No\nYes",
@@ -1412,6 +1730,8 @@
   {
    "fieldname": "c_form_no",
    "fieldtype": "Link",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "C-Form No",
    "no_copy": 1,
    "options": "C-Form",
@@ -1421,12 +1741,16 @@
   {
    "fieldname": "column_break8",
    "fieldtype": "Column Break",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "oldfieldtype": "Column Break",
    "print_hide": 1
   },
   {
    "fieldname": "remarks",
    "fieldtype": "Small Text",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Remarks",
    "no_copy": 1,
    "oldfieldname": "remarks",
@@ -1438,6 +1762,8 @@
    "collapsible_depends_on": "sales_partner",
    "fieldname": "sales_team_section_break",
    "fieldtype": "Section Break",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Commission",
    "oldfieldtype": "Section Break",
    "options": "fa fa-group",
@@ -1446,6 +1772,8 @@
   {
    "fieldname": "sales_partner",
    "fieldtype": "Link",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Sales Partner",
    "oldfieldname": "sales_partner",
    "oldfieldtype": "Link",
@@ -1455,6 +1783,8 @@
   {
    "fieldname": "column_break10",
    "fieldtype": "Column Break",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "oldfieldtype": "Column Break",
    "print_hide": 1,
    "width": "50%"
@@ -1462,6 +1792,8 @@
   {
    "fieldname": "commission_rate",
    "fieldtype": "Float",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Commission Rate (%)",
    "oldfieldname": "commission_rate",
    "oldfieldtype": "Currency",
@@ -1470,6 +1802,8 @@
   {
    "fieldname": "total_commission",
    "fieldtype": "Currency",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Total Commission",
    "oldfieldname": "total_commission",
    "oldfieldtype": "Currency",
@@ -1481,6 +1815,8 @@
    "collapsible_depends_on": "sales_team",
    "fieldname": "section_break2",
    "fieldtype": "Section Break",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Sales Team",
    "print_hide": 1
   },
@@ -1488,6 +1824,8 @@
    "allow_on_submit": 1,
    "fieldname": "sales_team",
    "fieldtype": "Table",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Sales Team1",
    "oldfieldname": "sales_team",
    "oldfieldtype": "Table",
@@ -1495,14 +1833,19 @@
    "print_hide": 1
   },
   {
+   "collapsible": 1,
    "fieldname": "subscription_section",
    "fieldtype": "Section Break",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Subscription Section"
   },
   {
    "allow_on_submit": 1,
    "fieldname": "from_date",
    "fieldtype": "Date",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "From Date",
    "no_copy": 1,
    "print_hide": 1
@@ -1511,18 +1854,24 @@
    "allow_on_submit": 1,
    "fieldname": "to_date",
    "fieldtype": "Date",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "To Date",
    "no_copy": 1,
    "print_hide": 1
   },
   {
    "fieldname": "column_break_140",
-   "fieldtype": "Column Break"
+   "fieldtype": "Column Break",
+   "hide_days": 1,
+   "hide_seconds": 1
   },
   {
    "allow_on_submit": 1,
    "fieldname": "auto_repeat",
    "fieldtype": "Link",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Auto Repeat",
    "no_copy": 1,
    "options": "Auto Repeat",
@@ -1534,12 +1883,16 @@
    "depends_on": "eval: doc.auto_repeat",
    "fieldname": "update_auto_repeat_reference",
    "fieldtype": "Button",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Update Auto Repeat Reference"
   },
   {
    "fieldname": "against_income_account",
    "fieldtype": "Small Text",
    "hidden": 1,
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Against Income Account",
    "no_copy": 1,
    "oldfieldname": "against_income_account",
@@ -1551,6 +1904,8 @@
    "fieldname": "pos_total_qty",
    "fieldtype": "Float",
    "hidden": 1,
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Total Qty",
    "print_hide": 1,
    "print_hide_if_no_value": 1,
@@ -1560,17 +1915,30 @@
    "collapsible": 1,
    "fieldname": "accounting_dimensions_section",
    "fieldtype": "Section Break",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Accounting Dimensions"
   },
   {
    "fieldname": "dimension_col_break",
-   "fieldtype": "Column Break"
+   "fieldtype": "Column Break",
+   "hide_days": 1,
+   "hide_seconds": 1
+  },
+  {
+   "default": "0",
+   "fieldname": "is_consolidated",
+   "fieldtype": "Check",
+   "label": "Is Consolidated",
+   "read_only": 1
   },
   {
    "default": "0",
    "fetch_from": "customer.is_internal_customer",
    "fieldname": "is_internal_customer",
    "fieldtype": "Check",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Is Internal Customer",
    "read_only": 1
   }
@@ -1579,7 +1947,7 @@
  "idx": 181,
  "is_submittable": 1,
  "links": [],
- "modified": "2020-05-19 17:00:57.208696",
+ "modified": "2020-07-18 05:07:16.725974",
  "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 5e8279b..3dab054 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
@@ -8,8 +8,6 @@
 from frappe import _, msgprint, throw
 from erpnext.accounts.party import get_party_account, get_due_date
 from frappe.model.mapper import get_mapped_doc
-from erpnext.accounts.doctype.sales_invoice.pos import update_multi_mode_option
-
 from erpnext.controllers.selling_controller import SellingController
 from erpnext.accounts.utils import get_account_currency
 from erpnext.stock.doctype.delivery_note.delivery_note import update_billed_amount_based_on_so
@@ -133,7 +131,7 @@
 		if self.is_pos and self.is_return:
 			self.verify_payment_amount_is_negative()
 
-		if self.redeem_loyalty_points and self.loyalty_program and self.loyalty_points:
+		if self.redeem_loyalty_points and self.loyalty_program and self.loyalty_points and not self.is_consolidated:
 			validate_loyalty_points(self, self.loyalty_points)
 
 	def validate_fixed_asset(self):
@@ -200,13 +198,13 @@
 		update_linked_doc(self.doctype, self.name, self.inter_company_invoice_reference)
 
 		# create the loyalty point ledger entry if the customer is enrolled in any loyalty program
-		if not self.is_return and self.loyalty_program:
+		if not self.is_return and not self.is_consolidated and self.loyalty_program:
 			self.make_loyalty_point_entry()
-		elif self.is_return and self.return_against and self.loyalty_program:
+		elif self.is_return and self.return_against and not self.is_consolidated and self.loyalty_program:
 			against_si_doc = frappe.get_doc("Sales Invoice", self.return_against)
 			against_si_doc.delete_loyalty_point_entry()
 			against_si_doc.make_loyalty_point_entry()
-		if self.redeem_loyalty_points and self.loyalty_points:
+		if self.redeem_loyalty_points and not self.is_consolidated and self.loyalty_points:
 			self.apply_loyalty_points()
 
 		# Healthcare Service Invoice.
@@ -265,9 +263,9 @@
 		if frappe.db.get_single_value('Selling Settings', 'sales_update_frequency') == "Each Transaction":
 			update_company_current_month_sales(self.company)
 			self.update_project()
-		if not self.is_return and self.loyalty_program:
+		if not self.is_return and not self.is_consolidated and self.loyalty_program:
 			self.delete_loyalty_point_entry()
-		elif self.is_return and self.return_against and self.loyalty_program:
+		elif self.is_return and self.return_against and not self.is_consolidated and self.loyalty_program:
 			against_si_doc = frappe.get_doc("Sales Invoice", self.return_against)
 			against_si_doc.delete_loyalty_point_entry()
 			against_si_doc.make_loyalty_point_entry()
@@ -347,7 +345,7 @@
 
 		super(SalesInvoice, self).set_missing_values(for_validate)
 
-		print_format = pos.get("print_format_for_online") if pos else None
+		print_format = pos.get("print_format") if pos else None
 		if not print_format and not cint(frappe.db.get_value('Print Format', 'POS Invoice', 'disabled')):
 			print_format = 'POS Invoice'
 
@@ -420,8 +418,6 @@
 			self.account_for_change_amount = frappe.get_cached_value('Company',  self.company,  'default_cash_account')
 
 		if pos:
-			self.allow_print_before_pay = pos.allow_print_before_pay
-
 			if not for_validate:
 				self.tax_category = pos.get("tax_category")
 
@@ -432,8 +428,8 @@
 			if pos.get('account_for_change_amount'):
 				self.account_for_change_amount = pos.get('account_for_change_amount')
 
-			for fieldname in ('territory', 'naming_series', 'currency', 'letter_head', 'tc_name',
-				'company', 'select_print_heading', 'cash_bank_account', 'write_off_account', 'taxes_and_charges',
+			for fieldname in ('naming_series', 'currency', 'letter_head', 'tc_name',
+				'company', 'select_print_heading', 'write_off_account', 'taxes_and_charges',
 				'write_off_cost_center', 'apply_discount_on', 'cost_center'):
 					if (not for_validate) or (for_validate and not self.get(fieldname)):
 						self.set(fieldname, pos.get(fieldname))
@@ -790,7 +786,8 @@
 						if self.party_account_currency==self.company_currency else grand_total,
 					"against_voucher": self.return_against if cint(self.is_return) and self.return_against else self.name,
 					"against_voucher_type": self.doctype,
-					"cost_center": self.cost_center
+					"cost_center": self.cost_center,
+					"project": self.project
 				}, self.party_account_currency, item=self)
 			)
 
@@ -845,7 +842,8 @@
 							"credit_in_account_currency": (flt(item.base_net_amount, item.precision("base_net_amount"))
 								if account_currency==self.company_currency
 								else flt(item.net_amount, item.precision("net_amount"))),
-							"cost_center": item.cost_center
+							"cost_center": item.cost_center,
+							"project": item.project or self.project
 						}, account_currency, item=item)
 					)
 
@@ -926,7 +924,8 @@
 							if self.party_account_currency==self.company_currency else flt(self.change_amount),
 						"against_voucher": self.return_against if cint(self.is_return) and self.return_against else self.name,
 						"against_voucher_type": self.doctype,
-						"cost_center": self.cost_center
+						"cost_center": self.cost_center,
+						"project": self.project
 					}, self.party_account_currency, item=self)
 				)
 
@@ -959,7 +958,8 @@
 						else flt(self.write_off_amount, self.precision("write_off_amount"))),
 					"against_voucher": self.return_against if cint(self.is_return) else self.name,
 					"against_voucher_type": self.doctype,
-					"cost_center": self.cost_center
+					"cost_center": self.cost_center,
+					"project": self.project
 				}, self.party_account_currency, item=self)
 			)
 			gl_entries.append(
@@ -1109,14 +1109,18 @@
 			expiry_date=self.posting_date, include_expired_entry=True)
 		if lp_details and getdate(lp_details.from_date) <= getdate(self.posting_date) and \
 			(not lp_details.to_date or getdate(lp_details.to_date) >= getdate(self.posting_date)):
-			points_earned = cint(eligible_amount/lp_details.collection_factor)
+
+			collection_factor = lp_details.collection_factor if lp_details.collection_factor else 1.0
+			points_earned = cint(eligible_amount/collection_factor)
+
 			doc = frappe.get_doc({
 				"doctype": "Loyalty Point Entry",
 				"company": self.company,
 				"loyalty_program": lp_details.loyalty_program,
 				"loyalty_program_tier": lp_details.tier_name,
 				"customer": self.customer,
-				"sales_invoice": self.name,
+				"invoice_type": self.doctype,
+				"invoice": self.name,
 				"loyalty_points": points_earned,
 				"purchase_amount": eligible_amount,
 				"expiry_date": add_days(self.posting_date, lp_details.expiry_duration),
@@ -1128,18 +1132,18 @@
 
 	# valdite the redemption and then delete the loyalty points earned on cancel of the invoice
 	def delete_loyalty_point_entry(self):
-		lp_entry = frappe.db.sql("select name from `tabLoyalty Point Entry` where sales_invoice=%s",
+		lp_entry = frappe.db.sql("select name from `tabLoyalty Point Entry` where invoice=%s",
 			(self.name), as_dict=1)
 
 		if not lp_entry: return
-		against_lp_entry = frappe.db.sql('''select name, sales_invoice from `tabLoyalty Point Entry`
+		against_lp_entry = frappe.db.sql('''select name, invoice from `tabLoyalty Point Entry`
 			where redeem_against=%s''', (lp_entry[0].name), as_dict=1)
 		if against_lp_entry:
-			invoice_list = ", ".join([d.sales_invoice for d in against_lp_entry])
-			frappe.throw(_('''Sales Invoice can't be cancelled since the Loyalty Points earned has been redeemed.
-				First cancel the Sales Invoice No {0}''').format(invoice_list))
+			invoice_list = ", ".join([d.invoice for d in against_lp_entry])
+			frappe.throw(_('''{} can't be cancelled since the Loyalty Points earned has been redeemed.
+				First cancel the {} No {}''').format(self.doctype, self.doctype, invoice_list))
 		else:
-			frappe.db.sql('''delete from `tabLoyalty Point Entry` where sales_invoice=%s''', (self.name))
+			frappe.db.sql('''delete from `tabLoyalty Point Entry` where invoice=%s''', (self.name))
 			# Set loyalty program
 			self.set_loyalty_program_tier()
 
@@ -1165,7 +1169,9 @@
 
 		points_to_redeem = self.loyalty_points
 		for lp_entry in loyalty_point_entries:
-			if lp_entry.sales_invoice == self.name:
+			if lp_entry.invoice_type != self.doctype or lp_entry.invoice == self.name:
+				# redeemption should be done against same doctype
+				# also it shouldn't be against itself
 				continue
 			available_points = lp_entry.loyalty_points - flt(redemption_details.get(lp_entry.name))
 			if available_points > points_to_redeem:
@@ -1178,7 +1184,8 @@
 				"loyalty_program": self.loyalty_program,
 				"loyalty_program_tier": lp_entry.loyalty_program_tier,
 				"customer": self.customer,
-				"sales_invoice": self.name,
+				"invoice_type": self.doctype,
+				"invoice": self.name,
 				"redeem_against": lp_entry.name,
 				"loyalty_points": -1*redeemed_points,
 				"purchase_amount": self.grand_total,
@@ -1569,13 +1576,13 @@
 	from erpnext.selling.doctype.customer.customer import get_loyalty_programs
 
 	customer = frappe.get_doc('Customer', customer)
-	if customer.loyalty_program: return
+	if customer.loyalty_program: return [customer.loyalty_program]
 
 	lp_details = get_loyalty_programs(customer)
 
 	if len(lp_details) == 1:
 		frappe.db.set(customer, 'loyalty_program', lp_details[0])
-		return []
+		return lp_details
 	else:
 		return lp_details
 
@@ -1595,3 +1602,71 @@
 	})
 
 	return invoice_discounting
+
+def update_multi_mode_option(doc, pos_profile):
+	def append_payment(payment_mode):
+		payment = doc.append('payments', {})
+		payment.default = payment_mode.default
+		payment.mode_of_payment = payment_mode.parent
+		payment.account = payment_mode.default_account
+		payment.type = payment_mode.type
+
+	doc.set('payments', [])
+	if not pos_profile or not pos_profile.get('payments'):
+		for payment_mode in get_all_mode_of_payments(doc):
+			append_payment(payment_mode)
+		return
+
+	for pos_payment_method in pos_profile.get('payments'):
+		pos_payment_method = pos_payment_method.as_dict()
+		
+		payment_mode = get_mode_of_payment_info(pos_payment_method.mode_of_payment, doc.company)
+		payment_mode[0].default = pos_payment_method.default
+		append_payment(payment_mode[0])
+
+def get_all_mode_of_payments(doc):
+	return frappe.db.sql("""
+		select mpa.default_account, mpa.parent, mp.type as type 
+		from `tabMode of Payment Account` mpa,`tabMode of Payment` mp 
+		where mpa.parent = mp.name and mpa.company = %(company)s and mp.enabled = 1""",
+	{'company': doc.company}, as_dict=1)
+
+def get_mode_of_payment_info(mode_of_payment, company):
+	return frappe.db.sql("""
+		select mpa.default_account, mpa.parent, mp.type as type 
+		from `tabMode of Payment Account` mpa,`tabMode of Payment` mp 
+		where mpa.parent = mp.name and mpa.company = %s and mp.enabled = 1 and mp.name = %s""",
+	(company, mode_of_payment), as_dict=1)
+
+def create_dunning(source_name, target_doc=None):
+	from frappe.model.mapper import get_mapped_doc
+	from erpnext.accounts.doctype.dunning.dunning import get_dunning_letter_text, calculate_interest_and_amount
+	def set_missing_values(source, target):
+		target.sales_invoice = source_name
+		target.outstanding_amount = source.outstanding_amount
+		overdue_days = (getdate(target.posting_date) - getdate(source.due_date)).days
+		target.overdue_days = overdue_days
+		if frappe.db.exists('Dunning Type', {'start_day': [
+	                                '<', overdue_days], 'end_day': ['>=', overdue_days]}):
+			dunning_type = frappe.get_doc('Dunning Type', {'start_day': [
+	                                '<', overdue_days], 'end_day': ['>=', overdue_days]})
+			target.dunning_type = dunning_type.name
+			target.rate_of_interest = dunning_type.rate_of_interest
+			target.dunning_fee = dunning_type.dunning_fee
+			letter_text = get_dunning_letter_text(dunning_type = dunning_type.name, doc = target.as_dict())
+			if letter_text:
+				target.body_text = letter_text.get('body_text')
+				target.closing_text = letter_text.get('closing_text')
+				target.language = letter_text.get('language')
+			amounts = calculate_interest_and_amount(target.posting_date, target.outstanding_amount,
+				target.rate_of_interest, target.dunning_fee, target.overdue_days)
+			target.interest_amount = amounts.get('interest_amount')
+			target.dunning_amount = amounts.get('dunning_amount')
+			target.grand_total = amounts.get('grand_total')
+
+	doclist = get_mapped_doc("Sales Invoice", source_name,	{
+		"Sales Invoice": {
+			"doctype": "Dunning",
+		}
+	}, target_doc, set_missing_values)
+	return doclist
diff --git a/erpnext/accounts/doctype/sales_invoice/test_records.json b/erpnext/accounts/doctype/sales_invoice/test_records.json
index ebe6e3d..11ebe6a 100644
--- a/erpnext/accounts/doctype/sales_invoice/test_records.json
+++ b/erpnext/accounts/doctype/sales_invoice/test_records.json
@@ -3,6 +3,7 @@
   "company": "_Test Company",
   "conversion_rate": 1.0,
   "currency": "INR",
+  "cost_center": "_Test Cost Center - _TC",
   "customer": "_Test Customer",
   "customer_name": "_Test Customer",
   "debit_to": "_Test Receivable - _TC",
@@ -37,7 +38,8 @@
     "charge_type": "On Net Total",
     "description": "VAT",
     "doctype": "Sales Taxes and Charges",
-    "parentfield": "taxes",
+	"parentfield": "taxes",
+	"cost_center": "_Test Cost Center - _TC",
     "rate": 6
    },
    {
@@ -45,7 +47,8 @@
     "charge_type": "On Net Total",
     "description": "Service Tax",
     "doctype": "Sales Taxes and Charges",
-    "parentfield": "taxes",
+	"parentfield": "taxes",
+	"cost_center": "_Test Cost Center - _TC",
     "rate": 6.36
    }
   ],
@@ -76,6 +79,7 @@
   "customer_name": "_Test Customer",
   "debit_to": "_Test Receivable - _TC",
   "doctype": "Sales Invoice",
+  "cost_center": "_Test Cost Center - _TC",
   "items": [
    {
     "amount": 500.0,
@@ -107,7 +111,8 @@
     "charge_type": "On Net Total",
     "description": "VAT",
     "doctype": "Sales Taxes and Charges",
-    "parentfield": "taxes",
+	"parentfield": "taxes",
+	"cost_center": "_Test Cost Center - _TC",
     "rate": 16
    },
    {
@@ -115,7 +120,8 @@
     "charge_type": "On Net Total",
     "description": "Service Tax",
     "doctype": "Sales Taxes and Charges",
-    "parentfield": "taxes",
+	"parentfield": "taxes",
+	"cost_center": "_Test Cost Center - _TC",
     "rate": 10
    }
   ],
@@ -132,6 +138,7 @@
   "customer_name": "_Test Customer",
   "debit_to": "_Test Receivable - _TC",
   "doctype": "Sales Invoice",
+  "cost_center": "_Test Cost Center - _TC",
   "items": [
    {
     "cost_center": "_Test Cost Center - _TC",
@@ -259,6 +266,7 @@
   "customer_name": "_Test Customer",
   "debit_to": "_Test Receivable - _TC",
   "doctype": "Sales Invoice",
+  "cost_center": "_Test Cost Center - _TC",
   "items": [
    {
     "cost_center": "_Test Cost Center - _TC",
diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
index 6cdf9b5..964566a 100644
--- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
@@ -706,37 +706,15 @@
 
 		self.pos_gl_entry(si, pos, 50)
 
-	def test_pos_returns_without_repayment(self):
-		pos_profile = make_pos_profile()
-
-		pos = create_sales_invoice(qty = 10, do_not_save=True)
-		pos.is_pos = 1
-		pos.pos_profile = pos_profile.name
-
-		pos.append("payments", {'mode_of_payment': 'Bank Draft', 'account': '_Test Bank - _TC', 'amount': 500})
-		pos.append("payments", {'mode_of_payment': 'Cash', 'account': 'Cash - _TC', 'amount': 500})
-		pos.insert()
-		pos.submit()
-
-		pos_return = create_sales_invoice(is_return=1,
-			return_against=pos.name, qty=-5, do_not_save=True)
-
-		pos_return.is_pos = 1
-		pos_return.pos_profile = pos_profile.name
-
-		pos_return.insert()
-		pos_return.submit()
-
-		self.assertFalse(pos_return.is_pos)
-		self.assertFalse(pos_return.get('payments'))
-
 	def test_pos_returns_with_repayment(self):
+		from erpnext.accounts.doctype.sales_invoice.sales_invoice import make_sales_return
+
 		pos_profile = make_pos_profile()
 
+		pos_profile.payments = []
 		pos_profile.append('payments', {
 			'default': 1,
-			'mode_of_payment': 'Cash',
-			'amount': 0.0
+			'mode_of_payment': 'Cash'
 		})
 
 		pos_profile.save()
@@ -751,18 +729,12 @@
 		pos.insert()
 		pos.submit()
 
-		pos_return = create_sales_invoice(is_return=1,
-			return_against=pos.name, qty=-5, do_not_save=True)
+		pos_return = make_sales_return(pos.name)
 
-		pos_return.is_pos = 1
-		pos_return.pos_profile = pos_profile.name
 		pos_return.insert()
 		pos_return.submit()
 
-		self.assertEqual(pos_return.get('payments')[0].amount, -500)
-		pos_profile.payments = []
-		pos_profile.save()
-
+		self.assertEqual(pos_return.get('payments')[0].amount, -1000)
 
 	def test_pos_change_amount(self):
 		make_pos_profile()
@@ -788,82 +760,6 @@
 		self.assertEqual(pos.grand_total, 100.0)
 		self.assertEqual(pos.write_off_amount, -5)
 
-	def test_make_pos_invoice(self):
-		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",
-			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
-
-		pos.append("payments", {'mode_of_payment': 'Bank Draft', 'account': '_Test Bank - TCP1', 'amount': 50})
-		pos.append("payments", {'mode_of_payment': 'Cash', 'account': 'Cash - TCP1', 'amount': 50})
-
-		taxes = get_taxes_and_charges()
-		pos.taxes = []
-		for tax in taxes:
-			pos.append("taxes", tax)
-
-		invoice_data = [{'09052016142': pos}]
-		si = make_invoice(pos_profile, invoice_data).get('invoice')
-		self.assertEqual(si[0], '09052016142')
-
-		sales_invoice = frappe.get_all('Sales Invoice', fields =["*"], filters = {'offline_pos_name': '09052016142', 'docstatus': 1})
-		si = frappe.get_doc('Sales Invoice', sales_invoice[0].name)
-
-		self.assertEqual(si.grand_total, 100)
-
-		self.pos_gl_entry(si, pos, 50)
-
-	def test_make_pos_invoice_in_draft(self):
-		from erpnext.accounts.doctype.sales_invoice.pos import make_invoice
-		from erpnext.stock.doctype.item.test_item import make_item
-
-		allow_negative_stock = frappe.db.get_single_value('Stock Settings', 'allow_negative_stock')
-		if allow_negative_stock:
-			frappe.db.set_value('Stock Settings', None, 'allow_negative_stock', 0)
-
-		pos_profile = make_pos_profile()
-		timestamp = cint(time.time())
-
-		item = make_item("_Test POS Item")
-		pos = copy.deepcopy(test_records[1])
-		pos['items'][0]['item_code'] = item.name
-		pos['items'][0]['warehouse'] = "_Test Warehouse - _TC"
-		pos["is_pos"] = 1
-		pos["offline_pos_name"] = timestamp
-		pos["update_stock"] = 1
-		pos["payments"] = [{'mode_of_payment': 'Bank Draft', 'account': '_Test Bank - _TC', 'amount': 300},
-							{'mode_of_payment': 'Cash', 'account': 'Cash - _TC', 'amount': 330}]
-
-		invoice_data = [{timestamp: pos}]
-		si = make_invoice(pos_profile, invoice_data).get('invoice')
-		self.assertEqual(si[0], timestamp)
-
-		sales_invoice = frappe.get_all('Sales Invoice', fields =["*"], filters = {'offline_pos_name': timestamp})
-		self.assertEqual(sales_invoice[0].docstatus, 0)
-
-		timestamp = cint(time.time())
-		pos["offline_pos_name"] = timestamp
-		invoice_data = [{timestamp: pos}]
-		si1 = make_invoice(pos_profile, invoice_data).get('invoice')
-		self.assertEqual(si1[0], timestamp)
-
-		sales_invoice1 = frappe.get_all('Sales Invoice', fields =["*"], filters = {'offline_pos_name': timestamp})
-		self.assertEqual(sales_invoice1[0].docstatus, 0)
-
-		if allow_negative_stock:
-			frappe.db.set_value('Stock Settings', None, 'allow_negative_stock', 1)
-
 	def pos_gl_entry(self, si, pos, cash_amount):
 		# check stock ledger entries
 		sle = frappe.db.sql("""select * from `tabStock Ledger Entry`
@@ -1640,11 +1536,8 @@
 		si_doc = frappe.get_doc('Sales Invoice', si.name)
 		self.assertEqual(si_doc.outstanding_amount, 0)
 
-	def test_sales_invoice_for_enable_allow_cost_center_in_entry_of_bs_account(self):
+	def test_sales_invoice_with_cost_center(self):
 		from erpnext.accounts.doctype.cost_center.test_cost_center import create_cost_center
-		accounts_settings = frappe.get_doc('Accounts Settings', 'Accounts Settings')
-		accounts_settings.allow_cost_center_in_entry_of_bs_account = 1
-		accounts_settings.save()
 		cost_center = "_Test Cost Center for BS Account - _TC"
 		create_cost_center(cost_center_name="_Test Cost Center for BS Account", company="_Test Company")
 
@@ -1669,14 +1562,47 @@
 
 		for gle in gl_entries:
 			self.assertEqual(expected_values[gle.account]["cost_center"], gle.cost_center)
+	
+	def test_sales_invoice_with_project_link(self):
+		from erpnext.projects.doctype.project.test_project import make_project
 
-		accounts_settings.allow_cost_center_in_entry_of_bs_account = 0
-		accounts_settings.save()
+		project = make_project({
+			'project_name': 'Sales Invoice Project',
+			'project_template_name': 'Test Project Template',
+			'start_date': '2020-01-01'
+		})
+		item_project = make_project({
+			'project_name': 'Sales Invoice Item Project',
+			'project_template_name': 'Test Project Template',
+			'start_date': '2019-06-01'
+		})
 
-	def test_sales_invoice_for_disable_allow_cost_center_in_entry_of_bs_account(self):
-		accounts_settings = frappe.get_doc('Accounts Settings', 'Accounts Settings')
-		accounts_settings.allow_cost_center_in_entry_of_bs_account = 1
-		accounts_settings.save()
+		sales_invoice = create_sales_invoice(do_not_save=1)
+		sales_invoice.items[0].project = item_project.project_name
+		sales_invoice.project = project.project_name
+
+		sales_invoice.submit()
+
+		expected_values = {
+			"Debtors - _TC": {
+				"project": project.project_name
+			},
+			"Sales - _TC": {
+				"project": item_project.project_name
+			}
+		}
+
+		gl_entries = frappe.db.sql("""select account, cost_center, project, account_currency, debit, credit,
+			debit_in_account_currency, credit_in_account_currency
+			from `tabGL Entry` where voucher_type='Sales Invoice' and voucher_no=%s
+			order by account asc""", sales_invoice.name, as_dict=1)
+		
+		self.assertTrue(gl_entries)
+		
+		for gle in gl_entries:
+			self.assertEqual(expected_values[gle.account]["project"], gle.project)
+
+	def test_sales_invoice_without_cost_center(self):
 		cost_center = "_Test Cost Center - _TC"
 		si =  create_sales_invoice(debit_to="Debtors - _TC")
 
@@ -1699,9 +1625,6 @@
 		for gle in gl_entries:
 			self.assertEqual(expected_values[gle.account]["cost_center"], gle.cost_center)
 
-		accounts_settings.allow_cost_center_in_entry_of_bs_account = 0
-		accounts_settings.save()
-
 	def test_deferred_revenue(self):
 		deferred_account = create_account(account_name="Deferred Revenue",
 			parent_account="Current Liabilities - _TC", company="_Test Company")
@@ -1720,8 +1643,6 @@
 		si.save()
 		si.submit()
 
-		from erpnext.accounts.deferred_revenue import convert_deferred_revenue_to_income
-
 		pda1 = frappe.get_doc(dict(
 			doctype='Process Deferred Accounting',
 			posting_date=nowdate(),
@@ -1745,6 +1666,55 @@
 
 		check_gl_entries(self, si.name, expected_gle, "2019-01-30")
 
+	def test_fixed_deferred_revenue(self):
+		deferred_account = create_account(account_name="Deferred Revenue",
+			parent_account="Current Liabilities - _TC", company="_Test Company")
+
+		acc_settings = frappe.get_doc('Accounts Settings', 'Accounts Settings')
+		acc_settings.book_deferred_entries_based_on = 'Months'
+		acc_settings.save()
+
+		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-16", rate=50000, do_not_submit=True)
+		si.items[0].enable_deferred_revenue = 1
+		si.items[0].service_start_date = "2019-01-16"
+		si.items[0].service_end_date = "2019-03-31"
+		si.items[0].deferred_revenue_account = deferred_account
+		si.save()
+		si.submit()
+
+		pda1 = frappe.get_doc(dict(
+			doctype='Process Deferred Accounting',
+			posting_date='2019-03-31',
+			start_date="2019-01-01",
+			end_date="2019-03-31",
+			type="Income",
+			company="_Test Company"
+		))
+
+		pda1.insert()
+		pda1.submit()
+
+		expected_gle = [
+			[deferred_account, 10000.0, 0.0, "2019-01-31"],
+			["Sales - _TC", 0.0, 10000.0, "2019-01-31"],
+			[deferred_account, 20000.0, 0.0, "2019-02-28"],
+			["Sales - _TC", 0.0, 20000.0, "2019-02-28"],
+			[deferred_account, 20000.0, 0.0, "2019-03-31"],
+			["Sales - _TC", 0.0, 20000.0, "2019-03-31"]
+		]
+
+		check_gl_entries(self, si.name, expected_gle, "2019-01-30")
+
+		acc_settings = frappe.get_doc('Accounts Settings', 'Accounts Settings')
+		acc_settings.book_deferred_entries_based_on = 'Days'
+		acc_settings.save()
+
 	def test_inter_company_transaction(self):
 
 		if not frappe.db.exists("Customer", "_Test Internal Customer"):
diff --git a/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json b/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json
index b2294e4..004d358 100644
--- a/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json
+++ b/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json
@@ -94,6 +94,7 @@
   "accounting_dimensions_section",
   "cost_center",
   "dimension_col_break",
+  "project",
   "section_break_54",
   "page_break"
  ],
@@ -783,12 +784,18 @@
    "fieldtype": "Link",
    "label": "Finance Book",
    "options": "Finance Book"
+  },
+  {
+   "fieldname": "project",
+   "fieldtype": "Link",
+   "label": "Project",
+   "options": "Project"
   }
  ],
  "idx": 1,
  "istable": 1,
  "links": [],
- "modified": "2019-12-04 12:22:38.517710",
+ "modified": "2020-07-18 12:24:41.749986",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "Sales Invoice Item",
diff --git a/erpnext/accounts/doctype/sales_invoice_payment/sales_invoice_payment.json b/erpnext/accounts/doctype/sales_invoice_payment/sales_invoice_payment.json
index 52cf810..2f9d381 100644
--- a/erpnext/accounts/doctype/sales_invoice_payment/sales_invoice_payment.json
+++ b/erpnext/accounts/doctype/sales_invoice_payment/sales_invoice_payment.json
@@ -1,314 +1,90 @@
 {
- "allow_copy": 0, 
- "allow_events_in_timeline": 0, 
- "allow_guest_to_view": 0, 
- "allow_import": 0, 
- "allow_rename": 0, 
- "beta": 0, 
- "creation": "2016-05-08 23:49:38.842621", 
- "custom": 0, 
- "docstatus": 0, 
- "doctype": "DocType", 
- "document_type": "", 
- "editable_grid": 1, 
+ "actions": [],
+ "creation": "2016-05-08 23:49:38.842621",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "default",
+  "mode_of_payment",
+  "amount",
+  "column_break_3",
+  "account",
+  "type",
+  "base_amount",
+  "clearance_date"
+ ],
  "fields": [
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "depends_on": "eval:parent.doctype == 'POS Profile'", 
-   "fetch_if_empty": 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, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "mode_of_payment",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "label": "Mode of Payment",
+   "options": "Mode of Payment",
+   "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": "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": 1, 
-   "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": 1, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "default": "0",
+   "depends_on": "eval:parent.doctype == 'Sales Invoice'",
+   "fieldname": "amount",
+   "fieldtype": "Currency",
+   "in_list_view": 1,
+   "label": "Amount",
+   "options": "currency",
+   "reqd": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "default": "0", 
-   "depends_on": "eval:parent.doctype == 'Sales Invoice'", 
-   "fetch_if_empty": 0, 
-   "fieldname": "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": "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
-  }, 
+   "fieldname": "column_break_3",
+   "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": "column_break_3", 
-   "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": "account",
+   "fieldtype": "Link",
+   "label": "Account",
+   "options": "Account",
+   "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": "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": "Account", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Account", 
-   "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
-  }, 
+   "fetch_from": "mode_of_payment.type",
+   "fieldname": "type",
+   "fieldtype": "Read Only",
+   "label": "Type"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fetch_from": "mode_of_payment.type", 
-   "fetch_if_empty": 0, 
-   "fieldname": "type", 
-   "fieldtype": "Read Only", 
-   "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": "Type", 
-   "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
-  }, 
+   "fieldname": "base_amount",
+   "fieldtype": "Currency",
+   "label": "Base Amount (Company Currency)",
+   "no_copy": 1,
+   "options": "Company:company:default_currency",
+   "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": "base_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": "Base Amount (Company Currency)", 
-   "length": 0, 
-   "no_copy": 1, 
-   "options": "Company:company:default_currency", 
-   "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
-  }, 
+   "fieldname": "clearance_date",
+   "fieldtype": "Date",
+   "label": "Clearance Date",
+   "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": "clearance_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": "Clearance Date", 
-   "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
+   "default": "0",
+   "fieldname": "default",
+   "fieldtype": "Check",
+   "hidden": 1,
+   "label": "Default",
+   "read_only": 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": "2019-03-19 14:54:56.524556", 
- "modified_by": "Administrator", 
- "module": "Accounts", 
- "name": "Sales Invoice Payment", 
- "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": 0, 
- "track_seen": 0, 
- "track_views": 0
+ ],
+ "istable": 1,
+ "links": [],
+ "modified": "2020-05-05 16:51:20.091441",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "Sales Invoice Payment",
+ "owner": "Administrator",
+ "permissions": [],
+ "quick_entry": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC"
 }
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/subscription/subscription.js b/erpnext/accounts/doctype/subscription/subscription.js
index dcbec12..ba98eb9 100644
--- a/erpnext/accounts/doctype/subscription/subscription.js
+++ b/erpnext/accounts/doctype/subscription/subscription.js
@@ -2,6 +2,16 @@
 // For license information, please see license.txt
 
 frappe.ui.form.on('Subscription', {
+	setup: function(frm) {
+		frm.set_query('party_type', function() {
+			return {
+				filters : {
+					name: ['in', ['Customer', 'Supplier']]
+				}
+			}
+		});
+	},
+
 	refresh: function(frm) {
 		if(!frm.is_new()){
 			if(frm.doc.status !== 'Cancelled'){
diff --git a/erpnext/accounts/doctype/subscription/subscription.json b/erpnext/accounts/doctype/subscription/subscription.json
index 32b97ba..afb94fe 100644
--- a/erpnext/accounts/doctype/subscription/subscription.json
+++ b/erpnext/accounts/doctype/subscription/subscription.json
@@ -6,14 +6,18 @@
  "editable_grid": 1,
  "engine": "InnoDB",
  "field_order": [
-  "customer",
-  "cb_1",
+  "party_type",
   "status",
+  "cb_1",
+  "party",
   "subscription_period",
-  "start",
+  "start_date",
+  "end_date",
   "cancelation_date",
   "trial_period_start",
   "trial_period_end",
+  "follow_calendar_months",
+  "generate_new_invoices_past_due_date",
   "column_break_11",
   "current_invoice_start",
   "current_invoice_end",
@@ -23,7 +27,8 @@
   "sb_4",
   "plans",
   "sb_1",
-  "tax_template",
+  "sales_tax_template",
+  "purchase_tax_template",
   "sb_2",
   "apply_additional_discount",
   "cb_2",
@@ -32,19 +37,11 @@
   "sb_3",
   "invoices",
   "accounting_dimensions_section",
+  "cost_center",
   "dimension_col_break"
  ],
  "fields": [
   {
-   "fieldname": "customer",
-   "fieldtype": "Link",
-   "in_list_view": 1,
-   "label": "Customer",
-   "options": "Customer",
-   "reqd": 1,
-   "set_only_once": 1
-  },
-  {
    "allow_on_submit": 1,
    "fieldname": "cb_1",
    "fieldtype": "Column Break"
@@ -53,7 +50,7 @@
    "fieldname": "status",
    "fieldtype": "Select",
    "label": "Status",
-   "options": "\nTrialling\nActive\nPast Due Date\nCancelled\nUnpaid",
+   "options": "\nTrialling\nActive\nPast Due Date\nCancelled\nUnpaid\nCompleted",
    "read_only": 1
   },
   {
@@ -62,12 +59,6 @@
    "label": "Subscription Period"
   },
   {
-   "fieldname": "start",
-   "fieldtype": "Date",
-   "label": "Subscription Start Date",
-   "set_only_once": 1
-  },
-  {
    "fieldname": "cancelation_date",
    "fieldtype": "Date",
    "label": "Cancelation Date",
@@ -137,17 +128,12 @@
    "reqd": 1
   },
   {
+   "depends_on": "eval:['Customer', 'Supplier'].includes(doc.party_type)",
    "fieldname": "sb_1",
    "fieldtype": "Section Break",
    "label": "Taxes"
   },
   {
-   "fieldname": "tax_template",
-   "fieldtype": "Link",
-   "label": "Sales Taxes and Charges Template",
-   "options": "Sales Taxes and Charges Template"
-  },
-  {
    "fieldname": "sb_2",
    "fieldtype": "Section Break",
    "label": "Discounts"
@@ -195,10 +181,74 @@
   {
    "fieldname": "dimension_col_break",
    "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "party_type",
+   "fieldtype": "Link",
+   "label": "Party Type",
+   "options": "DocType",
+   "reqd": 1,
+   "set_only_once": 1
+  },
+  {
+   "fieldname": "party",
+   "fieldtype": "Dynamic Link",
+   "in_list_view": 1,
+   "label": "Party",
+   "options": "party_type",
+   "reqd": 1,
+   "set_only_once": 1
+  },
+  {
+   "depends_on": "eval:doc.party_type === 'Customer'",
+   "fieldname": "sales_tax_template",
+   "fieldtype": "Link",
+   "label": "Sales Taxes and Charges Template",
+   "options": "Sales Taxes and Charges Template"
+  },
+  {
+   "depends_on": "eval:doc.party_type === 'Supplier'",
+   "fieldname": "purchase_tax_template",
+   "fieldtype": "Link",
+   "label": "Purchase Taxes and Charges Template",
+   "options": "Purchase Taxes and Charges Template"
+  },
+  {
+   "default": "0",
+   "description": "If this is checked subsequent new invoices will be created on calendar  month and quarter start dates irrespective of current invoice start date",
+   "fieldname": "follow_calendar_months",
+   "fieldtype": "Check",
+   "label": "Follow Calendar Months",
+   "set_only_once": 1
+  },
+  {
+   "default": "0",
+   "description": "New invoices will be generated as per schedule even if current invoices are unpaid or past due date",
+   "fieldname": "generate_new_invoices_past_due_date",
+   "fieldtype": "Check",
+   "label": "Generate New Invoices Past Due Date"
+  },
+  {
+   "fieldname": "end_date",
+   "fieldtype": "Date",
+   "label": "Subscription End Date",
+   "set_only_once": 1
+  },
+  {
+   "fieldname": "start_date",
+   "fieldtype": "Date",
+   "label": "Subscription Start Date",
+   "set_only_once": 1
+  },
+  {
+   "fieldname": "cost_center",
+   "fieldtype": "Link",
+   "label": "Cost Center",
+   "options": "Cost Center"
   }
  ],
  "links": [],
- "modified": "2020-01-27 14:37:32.845173",
+ "modified": "2020-06-25 10:52:52.265105",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "Subscription",
diff --git a/erpnext/accounts/doctype/subscription/subscription.py b/erpnext/accounts/doctype/subscription/subscription.py
index 0933c7e..0752531 100644
--- a/erpnext/accounts/doctype/subscription/subscription.py
+++ b/erpnext/accounts/doctype/subscription/subscription.py
@@ -7,7 +7,7 @@
 import frappe
 from frappe import _
 from frappe.model.document import Document
-from frappe.utils.data import nowdate, getdate, cint, add_days, date_diff, get_last_day, add_to_date, flt
+from frappe.utils.data import nowdate, getdate, cstr, cint, add_days, date_diff, get_last_day, add_to_date, flt
 from erpnext.accounts.doctype.subscription_plan.subscription_plan import get_plan_rate
 from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_accounting_dimensions
 
@@ -15,7 +15,7 @@
 class Subscription(Document):
 	def before_insert(self):
 		# update start just before the subscription doc is created
-		self.update_subscription_period(self.start)
+		self.update_subscription_period(self.start_date)
 
 	def update_subscription_period(self, date=None):
 		"""
@@ -35,7 +35,9 @@
 		If the `date` parameter is not given , it will be automatically set as today's
 		date.
 		"""
-		if self.trial_period_start and self.is_trialling():
+		if self.is_new_subscription() and self.trial_period_end and getdate(self.trial_period_end) > getdate(self.start_date):
+			self.current_invoice_start = add_days(self.trial_period_end, 1)
+		elif self.trial_period_start and self.is_trialling():
 			self.current_invoice_start = self.trial_period_start
 		elif date:
 			self.current_invoice_start = date
@@ -53,15 +55,45 @@
 		current billing period where `x` is the billing interval from the
 		`Subscription Plan` in the `Subscription`.
 		"""
-		if self.is_trialling():
+		if self.is_trialling() and getdate(self.current_invoice_start) < getdate(self.trial_period_end):
 			self.current_invoice_end = self.trial_period_end
 		else:
 			billing_cycle_info = self.get_billing_cycle_data()
 			if billing_cycle_info:
-				self.current_invoice_end = add_to_date(self.current_invoice_start, **billing_cycle_info)
+				if self.is_new_subscription() and getdate(self.start_date) < getdate(self.current_invoice_start):
+					self.current_invoice_end = add_to_date(self.start_date, **billing_cycle_info)
+
+					# For cases where trial period is for an entire billing interval
+					if getdate(self.current_invoice_end) < getdate(self.current_invoice_start):
+						self.current_invoice_end = add_to_date(self.current_invoice_start, **billing_cycle_info)
+				else:
+					self.current_invoice_end = add_to_date(self.current_invoice_start, **billing_cycle_info)
 			else:
 				self.current_invoice_end = get_last_day(self.current_invoice_start)
 
+			if self.follow_calendar_months:
+				billing_info = self.get_billing_cycle_and_interval()
+				billing_interval_count = billing_info[0]['billing_interval_count']
+				calendar_months = get_calendar_months(billing_interval_count)
+				calendar_month = 0
+				current_invoice_end_month = getdate(self.current_invoice_end).month
+				current_invoice_end_year = getdate(self.current_invoice_end).year
+
+				for month in calendar_months:
+					if month <= current_invoice_end_month:
+						calendar_month = month
+
+				if cint(calendar_month - billing_interval_count) <= 0 and \
+					getdate(self.current_invoice_start).month != 1:
+					calendar_month = 12
+					current_invoice_end_year -= 1
+
+				self.current_invoice_end = get_last_day(cstr(current_invoice_end_year) + '-' \
+					+ cstr(calendar_month) + '-01')
+
+			if self.end_date and getdate(self.current_invoice_end) > getdate(self.end_date):
+				self.current_invoice_end = self.end_date
+
 	@staticmethod
 	def validate_plans_billing_cycle(billing_cycle_data):
 		"""
@@ -132,21 +164,22 @@
 		"""
 		if self.is_trialling():
 			self.status = 'Trialling'
-		elif self.status == 'Past Due Date' and self.is_past_grace_period():
+		elif self.status == 'Active' and self.end_date and getdate() > getdate(self.end_date):
+			self.status = 'Completed'
+		elif self.is_past_grace_period():
 			subscription_settings = frappe.get_single('Subscription Settings')
 			self.status = 'Cancelled' if cint(subscription_settings.cancel_after_grace) else 'Unpaid'
-		elif self.status == 'Past Due Date' and not self.has_outstanding_invoice():
-			self.status = 'Active'
-		elif self.current_invoice_is_past_due():
+		elif self.current_invoice_is_past_due() and not self.is_past_grace_period():
 			self.status = 'Past Due Date'
+		elif not self.has_outstanding_invoice():
+			self.status = 'Active'
 		elif self.is_new_subscription():
 			self.status = 'Active'
-			# todo: then generate new invoice
 		self.save()
 
 	def is_trialling(self):
 		"""
-		Returns `True` if the `Subscription` is trial period.
+		Returns `True` if the `Subscription` is in trial period.
 		"""
 		return not self.period_has_passed(self.trial_period_end) and self.is_new_subscription()
 
@@ -160,7 +193,7 @@
 			return True
 
 		end_date = getdate(end_date)
-		return getdate(nowdate()) > getdate(end_date)
+		return getdate() > getdate(end_date)
 
 	def is_past_grace_period(self):
 		"""
@@ -171,7 +204,7 @@
 			subscription_settings = frappe.get_single('Subscription Settings')
 			grace_period = cint(subscription_settings.grace_period)
 
-			return getdate(nowdate()) > add_days(current_invoice.due_date, grace_period)
+			return getdate() > add_days(current_invoice.due_date, grace_period)
 
 	def current_invoice_is_past_due(self, current_invoice=None):
 		"""
@@ -180,22 +213,24 @@
 		if not current_invoice:
 			current_invoice = self.get_current_invoice()
 
-		if not current_invoice:
+		if not current_invoice or self.is_paid(current_invoice):
 			return False
 		else:
-			return getdate(nowdate()) > getdate(current_invoice.due_date)
+			return getdate() > getdate(current_invoice.due_date)
 
 	def get_current_invoice(self):
 		"""
 		Returns the most recent generated invoice.
 		"""
+		doctype = 'Sales Invoice' if self.party_type == 'Customer' else 'Purchase Invoice'
+
 		if len(self.invoices):
 			current = self.invoices[-1]
-			if frappe.db.exists('Sales Invoice', current.invoice):
-				doc = frappe.get_doc('Sales Invoice', current.invoice)
+			if frappe.db.exists(doctype, current.get('invoice')):
+				doc = frappe.get_doc(doctype, current.get('invoice'))
 				return doc
 			else:
-				frappe.throw(_('Invoice {0} no longer exists').format(current.invoice))
+				frappe.throw(_('Invoice {0} no longer exists').format(current.get('invoice')))
 
 	def is_new_subscription(self):
 		"""
@@ -206,6 +241,8 @@
 	def validate(self):
 		self.validate_trial_period()
 		self.validate_plans_billing_cycle(self.get_billing_cycle_and_interval())
+		self.validate_end_date()
+		self.validate_to_follow_calendar_months()
 
 	def validate_trial_period(self):
 		"""
@@ -215,34 +252,72 @@
 			if getdate(self.trial_period_end) < getdate(self.trial_period_start):
 				frappe.throw(_('Trial Period End Date Cannot be before Trial Period Start Date'))
 
-		elif self.trial_period_start or self.trial_period_end:
+		if self.trial_period_start and not self.trial_period_end:
 			frappe.throw(_('Both Trial Period Start Date and Trial Period End Date must be set'))
 
+		if self.trial_period_start and getdate(self.trial_period_start) > getdate(self.start_date):
+			frappe.throw(_('Trial Period Start date cannot be after Subscription Start Date'))
+
+	def validate_end_date(self):
+		billing_cycle_info = self.get_billing_cycle_data()
+		end_date = add_to_date(self.start_date, **billing_cycle_info)
+
+		if self.end_date and getdate(self.end_date) <= getdate(end_date):
+			frappe.throw(_('Subscription End Date must be after {0} as per the subscription plan').format(end_date))
+
+	def validate_to_follow_calendar_months(self):
+		if self.follow_calendar_months:
+			billing_info = self.get_billing_cycle_and_interval()
+
+			if not self.end_date:
+				frappe.throw(_('Subscription End Date is mandatory to follow calendar months'))
+
+			if billing_info[0]['billing_interval'] != 'Month':
+				frappe.throw('Billing Interval in Subscription Plan must be Month to follow calendar months')
+
 	def after_insert(self):
 		# todo: deal with users who collect prepayments. Maybe a new Subscription Invoice doctype?
 		self.set_subscription_status()
 
 	def generate_invoice(self, prorate=0):
 		"""
-		Creates a `Sales Invoice` for the `Subscription`, updates `self.invoices` and
+		Creates a `Invoice` for the `Subscription`, updates `self.invoices` and
 		saves the `Subscription`.
 		"""
+
+		doctype = 'Sales Invoice' if self.party_type == 'Customer' else 'Purchase Invoice'
+
 		invoice = self.create_invoice(prorate)
-		self.append('invoices', {'invoice': invoice.name})
+		self.append('invoices', {
+			'document_type': doctype,
+			'invoice': invoice.name
+		})
+
 		self.save()
 
 		return invoice
 
 	def create_invoice(self, prorate):
 		"""
-		Creates a `Sales Invoice`, submits it and returns it
+		Creates a `Invoice`, submits it and returns it
 		"""
-		invoice = frappe.new_doc('Sales Invoice')
-		invoice.set_posting_time = 1
-		invoice.posting_date = self.current_invoice_start
-		invoice.customer = self.customer
+		doctype = 'Sales Invoice' if self.party_type == 'Customer' else 'Purchase Invoice'
 
-		## Add dimesnions in invoice for subscription:
+		invoice = frappe.new_doc(doctype)
+		invoice.set_posting_time = 1
+		invoice.posting_date = self.current_invoice_start if self.generate_invoice_at_period_start \
+			else self.current_invoice_end
+
+		invoice.cost_center = self.cost_center
+
+		if doctype == 'Sales Invoice':
+			invoice.customer = self.party
+		else:
+			invoice.supplier = self.party
+			if frappe.db.get_value('Supplier', self.party, 'tax_withholding_category'):
+				invoice.apply_tds = 1
+
+		## Add dimensions in invoice for subscription:
 		accounting_dimensions = get_accounting_dimensions()
 
 		for dimension in accounting_dimensions:
@@ -255,18 +330,25 @@
 		# for that reason
 		items_list = self.get_items_from_plans(self.plans, prorate)
 		for item in items_list:
-			invoice.append('items',	item)
+			invoice.append('items', item)
 
 		# Taxes
-		if self.tax_template:
-			invoice.taxes_and_charges = self.tax_template
+		tax_template = ''
+
+		if doctype == 'Sales Invoice' and self.sales_tax_template:
+			tax_template = self.sales_tax_template
+		if doctype == 'Purchase Invoice' and self.purchase_tax_template:
+			tax_template = self.purchase_tax_template
+
+		if tax_template:
+			invoice.taxes_and_charges = tax_template
 			invoice.set_taxes()
 
 		# Due date
 		invoice.append(
 			'payment_schedule',
 			{
-				'due_date': add_days(self.current_invoice_end, cint(self.days_until_due)),
+				'due_date': add_days(invoice.posting_date, cint(self.days_until_due)),
 				'invoice_portion': 100
 			}
 		)
@@ -300,13 +382,42 @@
 			prorate_factor = get_prorata_factor(self.current_invoice_end, self.current_invoice_start)
 
 		items = []
-		customer = self.customer
+		party = self.party
 		for plan in plans:
-			item_code = frappe.db.get_value("Subscription Plan", plan.plan, "item")
-			if not prorate:
-				items.append({'item_code': item_code, 'qty': plan.qty, 'rate': get_plan_rate(plan.plan, plan.qty, customer)})
+			plan_doc = frappe.get_doc('Subscription Plan', plan.plan)
+
+			item_code = plan_doc.item
+
+			if self.party == 'Customer':
+				deferred_field = 'enable_deferred_revenue'
 			else:
-				items.append({'item_code': item_code, 'qty': plan.qty, 'rate': (get_plan_rate(plan.plan, plan.qty, customer) * prorate_factor)})
+				deferred_field = 'enable_deferred_expense'
+
+			deferred = frappe.db.get_value('Item', item_code, deferred_field)
+
+			if not prorate:
+				item = {'item_code': item_code, 'qty': plan.qty, 'rate': get_plan_rate(plan.plan, plan.qty, party,
+					self.current_invoice_start, self.current_invoice_end), 'cost_center': plan_doc.cost_center}
+			else:
+				item = {'item_code': item_code, 'qty': plan.qty, 'rate': get_plan_rate(plan.plan, plan.qty, party,
+					self.current_invoice_start, self.current_invoice_end, prorate_factor), 'cost_center': plan_doc.cost_center}
+
+			if deferred:
+				item.update({
+					deferred_field: deferred,
+					'service_start_date': self.current_invoice_start,
+					'service_end_date': self.current_invoice_end
+				})
+
+			accounting_dimensions = get_accounting_dimensions()
+
+			for dimension in accounting_dimensions:
+				if plan_doc.get(dimension):
+					item.update({
+						dimension: plan_doc.get(dimension)
+					})
+
+			items.append(item)
 
 		return items
 
@@ -322,12 +433,13 @@
 		elif self.status in ['Past Due Date', 'Unpaid']:
 			self.process_for_past_due_date()
 
+		self.set_subscription_status()
+
 		self.save()
 
 	def is_postpaid_to_invoice(self):
-		return getdate(nowdate()) > getdate(self.current_invoice_end) or \
-			(getdate(nowdate()) >= getdate(self.current_invoice_end) and getdate(self.current_invoice_end) == getdate(self.current_invoice_start)) and \
-			not self.has_outstanding_invoice()
+		return getdate() > getdate(self.current_invoice_end) or \
+			(getdate() >= getdate(self.current_invoice_end) and getdate(self.current_invoice_end) == getdate(self.current_invoice_start))
 
 	def is_prepaid_to_invoice(self):
 		if not self.generate_invoice_at_period_start:
@@ -337,14 +449,12 @@
 			return True
 
 		# Check invoice dates and make sure it doesn't have outstanding invoices
-		return getdate(nowdate()) >= getdate(self.current_invoice_start) and not self.has_outstanding_invoice()
+		return getdate() >= getdate(self.current_invoice_start)
 
-	def is_current_invoice_paid(self):
-		if self.is_new_subscription():
-			return False
+	def is_current_invoice_generated(self):
+		invoice = self.get_current_invoice()
 
-		last_invoice = frappe.get_doc('Sales Invoice', self.invoices[-1].invoice)
-		if getdate(last_invoice.posting_date) == getdate(self.current_invoice_start) and last_invoice.status == 'Paid':
+		if invoice and getdate(self.current_invoice_start) <= getdate(invoice.posting_date) <= getdate(self.current_invoice_end):
 			return True
 
 		return False
@@ -358,21 +468,23 @@
 		2. Change the `Subscription` status to 'Past Due Date'
 		3. Change the `Subscription` status to 'Cancelled'
 		"""
-		if not self.is_current_invoice_paid() and (self.is_postpaid_to_invoice() or self.is_prepaid_to_invoice()):
-			self.generate_invoice()
-			if self.current_invoice_is_past_due():
-				self.status = 'Past Due Date'
+		if getdate() > getdate(self.current_invoice_end) and self.is_prepaid_to_invoice():
+			self.update_subscription_period(add_days(self.current_invoice_end, 1))
 
-		if self.current_invoice_is_past_due() and getdate(nowdate()) > getdate(self.current_invoice_end):
-			self.status = 'Past Due Date'
+		if not self.is_current_invoice_generated() and (self.is_postpaid_to_invoice() or self.is_prepaid_to_invoice()):
+			prorate = frappe.db.get_single_value('Subscription Settings', 'prorate')
+			self.generate_invoice(prorate)
 
-		if self.cancel_at_period_end and getdate(nowdate()) > getdate(self.current_invoice_end):
+		if self.cancel_at_period_end and getdate() > getdate(self.current_invoice_end):
 			self.cancel_subscription_at_period_end()
 
 	def cancel_subscription_at_period_end(self):
 		"""
 		Called when `Subscription.cancel_at_period_end` is truthy
 		"""
+		if self.end_date and getdate() < getdate(self.end_date):
+			return
+
 		self.status = 'Cancelled'
 		if not self.cancelation_date:
 			self.cancelation_date = nowdate()
@@ -390,14 +502,22 @@
 		if not current_invoice:
 			frappe.throw(_('Current invoice {0} is missing').format(current_invoice.invoice))
 		else:
-			if self.is_not_outstanding(current_invoice):
+			if not self.has_outstanding_invoice():
 				self.status = 'Active'
-				self.update_subscription_period(add_days(self.current_invoice_end, 1))
 			else:
 				self.set_status_grace_period()
 
+			if getdate() > getdate(self.current_invoice_end):
+				self.update_subscription_period(add_days(self.current_invoice_end, 1))
+
+			# Generate invoices periodically even if current invoice are unpaid
+			if self.generate_new_invoices_past_due_date and not self.is_current_invoice_generated() and (self.is_postpaid_to_invoice()
+				or self.is_prepaid_to_invoice()):
+				prorate = frappe.db.get_single_value('Subscription Settings', 'prorate')
+				self.generate_invoice(prorate)
+
 	@staticmethod
-	def is_not_outstanding(invoice):
+	def is_paid(invoice):
 		"""
 		Return `True` if the given invoice is paid
 		"""
@@ -407,11 +527,17 @@
 		"""
 		Returns `True` if the most recent invoice for the `Subscription` is not paid
 		"""
+		doctype = 'Sales Invoice' if self.party_type == 'Customer' else 'Purchase Invoice'
 		current_invoice = self.get_current_invoice()
-		if not current_invoice:
-			return False
+		invoice_list = [d.invoice for d in self.invoices]
+
+		outstanding_invoices = frappe.get_all(doctype, fields=['name'],
+			filters={'status': ('!=', 'Paid'), 'name': ('in', invoice_list)})
+
+		if outstanding_invoices:
+			return True
 		else:
-			return not self.is_not_outstanding(current_invoice)
+			False
 
 	def cancel_subscription(self):
 		"""
@@ -419,7 +545,7 @@
 		but it will not affect already created invoices.
 		"""
 		if self.status != 'Cancelled':
-			to_generate_invoice = True if self.status == 'Active' else False
+			to_generate_invoice = True if self.status == 'Active' and not self.generate_invoice_at_period_start else False
 			to_prorate = frappe.db.get_single_value('Subscription Settings', 'prorate')
 			self.status = 'Cancelled'
 			self.cancelation_date = nowdate()
@@ -435,7 +561,7 @@
 		"""
 		if self.status == 'Cancelled':
 			self.status = 'Active'
-			self.db_set('start', nowdate())
+			self.db_set('start_date', nowdate())
 			self.update_subscription_period(nowdate())
 			self.invoices = []
 			self.save()
@@ -447,6 +573,14 @@
 		if invoice:
 			return invoice.precision('grand_total')
 
+def get_calendar_months(billing_interval):
+	calendar_months = []
+	start = 0
+	while start < 12:
+		start += billing_interval
+		calendar_months.append(start)
+
+	return calendar_months
 
 def get_prorata_factor(period_end, period_start):
 	diff = flt(date_diff(nowdate(), period_start) + 1)
@@ -469,10 +603,7 @@
 	"""
 	Returns all `Subscription` documents
 	"""
-	return frappe.db.sql(
-		'select name from `tabSubscription` where status != "Cancelled"',
-		as_dict=1
-	)
+	return frappe.db.get_all('Subscription', {'status': ('!=','Cancelled')})
 
 
 def process(data):
diff --git a/erpnext/accounts/doctype/subscription/subscription_list.js b/erpnext/accounts/doctype/subscription/subscription_list.js
index abcfc5e..a4edb77 100644
--- a/erpnext/accounts/doctype/subscription/subscription_list.js
+++ b/erpnext/accounts/doctype/subscription/subscription_list.js
@@ -4,6 +4,8 @@
 			return [__("Trialling"), "green"];
 		} else if(doc.status === 'Active') {
 			return [__("Active"), "green"];
+		} else if(doc.status === 'Completed') {
+				return [__("Completed"), "green"];
 		} else if(doc.status === 'Past Due Date') {
 			return [__("Past Due Date"), "orange"];
 		} else if(doc.status === 'Unpaid') {
diff --git a/erpnext/accounts/doctype/subscription/test_subscription.py b/erpnext/accounts/doctype/subscription/test_subscription.py
index 3d96f23..f41f08a 100644
--- a/erpnext/accounts/doctype/subscription/test_subscription.py
+++ b/erpnext/accounts/doctype/subscription/test_subscription.py
@@ -7,7 +7,7 @@
 
 import frappe
 from erpnext.accounts.doctype.subscription.subscription import get_prorata_factor
-from frappe.utils.data import nowdate, add_days, add_to_date, add_months, date_diff, flt
+from frappe.utils.data import nowdate, add_days, add_to_date, add_months, date_diff, flt, get_date_str
 
 
 def create_plan():
@@ -15,7 +15,7 @@
 		plan = frappe.new_doc('Subscription Plan')
 		plan.plan_name = '_Test Plan Name'
 		plan.item = '_Test Non Stock Item'
-		plan.price_determination = "Fixed rate"
+		plan.price_determination = "Fixed Rate"
 		plan.cost = 900
 		plan.billing_interval = 'Month'
 		plan.billing_interval_count = 1
@@ -25,7 +25,7 @@
 		plan = frappe.new_doc('Subscription Plan')
 		plan.plan_name = '_Test Plan Name 2'
 		plan.item = '_Test Non Stock Item'
-		plan.price_determination = "Fixed rate"
+		plan.price_determination = "Fixed Rate"
 		plan.cost = 1999
 		plan.billing_interval = 'Month'
 		plan.billing_interval_count = 1
@@ -35,12 +35,29 @@
 		plan = frappe.new_doc('Subscription Plan')
 		plan.plan_name = '_Test Plan Name 3'
 		plan.item = '_Test Non Stock Item'
-		plan.price_determination = "Fixed rate"
+		plan.price_determination = "Fixed Rate"
 		plan.cost = 1999
 		plan.billing_interval = 'Day'
 		plan.billing_interval_count = 14
 		plan.insert()
 
+	# Defined a quarterly Subscription Plan
+	if not frappe.db.exists('Subscription Plan', '_Test Plan Name 4'):
+		plan = frappe.new_doc('Subscription Plan')
+		plan.plan_name = '_Test Plan Name 4'
+		plan.item = '_Test Non Stock Item'
+		plan.price_determination = "Monthly Rate"
+		plan.cost = 20000
+		plan.billing_interval = 'Month'
+		plan.billing_interval_count = 3
+		plan.insert()
+
+	if not frappe.db.exists('Supplier', '_Test Supplier'):
+		supplier = frappe.new_doc('Supplier')
+		supplier.supplier_name = '_Test Supplier'
+		supplier.supplier_group = 'All Supplier Groups'
+		supplier.insert()
+
 class TestSubscription(unittest.TestCase):
 
 	def setUp(self):
@@ -48,7 +65,8 @@
 
 	def test_create_subscription_with_trial_with_correct_period(self):
 		subscription = frappe.new_doc('Subscription')
-		subscription.customer = '_Test Customer'
+		subscription.party_type = 'Customer'
+		subscription.party = '_Test Customer'
 		subscription.trial_period_start = nowdate()
 		subscription.trial_period_end = add_days(nowdate(), 30)
 		subscription.append('plans', {'plan': '_Test Plan Name', 'qty': 1})
@@ -56,8 +74,8 @@
 
 		self.assertEqual(subscription.trial_period_start, nowdate())
 		self.assertEqual(subscription.trial_period_end, add_days(nowdate(), 30))
-		self.assertEqual(subscription.trial_period_start, subscription.current_invoice_start)
-		self.assertEqual(subscription.trial_period_end, subscription.current_invoice_end)
+		self.assertEqual(add_days(subscription.trial_period_end, 1), get_date_str(subscription.current_invoice_start))
+		self.assertEqual(add_days(subscription.current_invoice_start, 30), get_date_str(subscription.current_invoice_end))
 		self.assertEqual(subscription.invoices, [])
 		self.assertEqual(subscription.status, 'Trialling')
 
@@ -65,7 +83,8 @@
 
 	def test_create_subscription_without_trial_with_correct_period(self):
 		subscription = frappe.new_doc('Subscription')
-		subscription.customer = '_Test Customer'
+		subscription.party_type = 'Customer'
+		subscription.party = '_Test Customer'
 		subscription.append('plans', {'plan': '_Test Plan Name', 'qty': 1})
 		subscription.save()
 
@@ -81,7 +100,8 @@
 
 	def test_create_subscription_trial_with_wrong_dates(self):
 		subscription = frappe.new_doc('Subscription')
-		subscription.customer = '_Test Customer'
+		subscription.party_type = 'Customer'
+		subscription.party = '_Test Customer'
 		subscription.trial_period_end = nowdate()
 		subscription.trial_period_start = add_days(nowdate(), 30)
 		subscription.append('plans', {'plan': '_Test Plan Name', 'qty': 1})
@@ -91,7 +111,8 @@
 
 	def test_create_subscription_multi_with_different_billing_fails(self):
 		subscription = frappe.new_doc('Subscription')
-		subscription.customer = '_Test Customer'
+		subscription.party_type = 'Customer'
+		subscription.party = '_Test Customer'
 		subscription.trial_period_end = nowdate()
 		subscription.trial_period_start = add_days(nowdate(), 30)
 		subscription.append('plans', {'plan': '_Test Plan Name', 'qty': 1})
@@ -102,8 +123,9 @@
 
 	def test_invoice_is_generated_at_end_of_billing_period(self):
 		subscription = frappe.new_doc('Subscription')
-		subscription.customer = '_Test Customer'
-		subscription.start = '2018-01-01'
+		subscription.party_type = 'Customer'
+		subscription.party = '_Test Customer'
+		subscription.start_date = '2018-01-01'
 		subscription.append('plans', {'plan': '_Test Plan Name', 'qty': 1})
 		subscription.insert()
 
@@ -114,18 +136,22 @@
 
 		self.assertEqual(len(subscription.invoices), 1)
 		self.assertEqual(subscription.current_invoice_start, '2018-01-01')
-		self.assertEqual(subscription.status, 'Past Due Date')
+		subscription.process()
+		self.assertEqual(subscription.status, 'Unpaid')
 		subscription.delete()
 
 	def test_status_goes_back_to_active_after_invoice_is_paid(self):
 		subscription = frappe.new_doc('Subscription')
-		subscription.customer = '_Test Customer'
+		subscription.party_type = 'Customer'
+		subscription.party = '_Test Customer'
 		subscription.append('plans', {'plan': '_Test Plan Name', 'qty': 1})
-		subscription.start = '2018-01-01'
+		subscription.start_date = '2018-01-01'
 		subscription.insert()
 		subscription.process()	# generate first invoice
 		self.assertEqual(len(subscription.invoices), 1)
-		self.assertEqual(subscription.status, 'Past Due Date')
+
+		# Status is unpaid as Days until Due is zero and grace period is Zero
+		self.assertEqual(subscription.status, 'Unpaid')
 
 		subscription.get_current_invoice()
 		current_invoice = subscription.get_current_invoice()
@@ -137,7 +163,7 @@
 		subscription.process()
 
 		self.assertEqual(subscription.status, 'Active')
-		self.assertEqual(subscription.current_invoice_start, add_months(subscription.start, 1))
+		self.assertEqual(subscription.current_invoice_start, add_months(subscription.start_date, 1))
 		self.assertEqual(len(subscription.invoices), 1)
 
 		subscription.delete()
@@ -149,16 +175,17 @@
 		settings.save()
 
 		subscription = frappe.new_doc('Subscription')
-		subscription.customer = '_Test Customer'
+		subscription.party_type = 'Customer'
+		subscription.party = '_Test Customer'
 		subscription.append('plans', {'plan': '_Test Plan Name', 'qty': 1})
-		subscription.start = '2018-01-01'
+		subscription.start_date = '2018-01-01'
 		subscription.insert()
+
+		self.assertEqual(subscription.status, 'Active')
+
 		subscription.process()		# generate first invoice
-
-		self.assertEqual(subscription.status, 'Past Due Date')
-
-		subscription.process()
 		# This should change status to Cancelled since grace period is 0
+		# And is backdated subscription so subscription will be cancelled after processing
 		self.assertEqual(subscription.status, 'Cancelled')
 
 		settings.cancel_after_grace = default_grace_period_action
@@ -172,16 +199,14 @@
 		settings.save()
 
 		subscription = frappe.new_doc('Subscription')
-		subscription.customer = '_Test Customer'
+		subscription.party_type = 'Customer'
+		subscription.party = '_Test Customer'
 		subscription.append('plans', {'plan': '_Test Plan Name', 'qty': 1})
-		subscription.start = '2018-01-01'
+		subscription.start_date = '2018-01-01'
 		subscription.insert()
 		subscription.process()		# generate first invoice
 
-		self.assertEqual(subscription.status, 'Past Due Date')
-
-		subscription.process()
-		# This should change status to Cancelled since grace period is 0
+		# Status is unpaid as Days until Due is zero and grace period is Zero
 		self.assertEqual(subscription.status, 'Unpaid')
 
 		settings.cancel_after_grace = default_grace_period_action
@@ -190,10 +215,11 @@
 
 	def test_subscription_invoice_days_until_due(self):
 		subscription = frappe.new_doc('Subscription')
-		subscription.customer = '_Test Customer'
+		subscription.party_type = 'Customer'
+		subscription.party = '_Test Customer'
 		subscription.append('plans', {'plan': '_Test Plan Name', 'qty': 1})
 		subscription.days_until_due = 10
-		subscription.start = add_months(nowdate(), -1)
+		subscription.start_date = add_months(nowdate(), -1)
 		subscription.insert()
 		subscription.process()		# generate first invoice
 		self.assertEqual(len(subscription.invoices), 1)
@@ -208,9 +234,10 @@
 		settings.save()
 
 		subscription = frappe.new_doc('Subscription')
-		subscription.customer = '_Test Customer'
+		subscription.party_type = 'Customer'
+		subscription.party = '_Test Customer'
 		subscription.append('plans', {'plan': '_Test Plan Name', 'qty': 1})
-		subscription.start = '2018-01-01'
+		subscription.start_date = '2018-01-01'
 		subscription.insert()
 		subscription.process()		# generate first invoice
 
@@ -232,7 +259,8 @@
 
 	def test_subscription_remains_active_during_invoice_period(self):
 		subscription = frappe.new_doc('Subscription')
-		subscription.customer = '_Test Customer'
+		subscription.party_type = 'Customer'
+		subscription.party = '_Test Customer'
 		subscription.append('plans', {'plan': '_Test Plan Name', 'qty': 1})
 		subscription.save()
 		subscription.process()		# no changes expected
@@ -258,7 +286,8 @@
 
 	def test_subscription_cancelation(self):
 		subscription = frappe.new_doc('Subscription')
-		subscription.customer = '_Test Customer'
+		subscription.party_type = 'Customer'
+		subscription.party = '_Test Customer'
 		subscription.append('plans', {'plan': '_Test Plan Name', 'qty': 1})
 		subscription.save()
 		subscription.cancel_subscription()
@@ -274,7 +303,8 @@
 		settings.save()
 
 		subscription = frappe.new_doc('Subscription')
-		subscription.customer = '_Test Customer'
+		subscription.party_type = 'Customer'
+		subscription.party = '_Test Customer'
 		subscription.append('plans', {'plan': '_Test Plan Name', 'qty': 1})
 		subscription.save()
 
@@ -309,7 +339,8 @@
 		settings.save()
 
 		subscription = frappe.new_doc('Subscription')
-		subscription.customer = '_Test Customer'
+		subscription.party_type = 'Customer'
+		subscription.party = '_Test Customer'
 		subscription.append('plans', {'plan': '_Test Plan Name', 'qty': 1})
 		subscription.save()
 		subscription.cancel_subscription()
@@ -329,7 +360,8 @@
 		settings.save()
 
 		subscription = frappe.new_doc('Subscription')
-		subscription.customer = '_Test Customer'
+		subscription.party_type = 'Customer'
+		subscription.party = '_Test Customer'
 		subscription.append('plans', {'plan': '_Test Plan Name', 'qty': 1})
 		subscription.save()
 		subscription.cancel_subscription()
@@ -353,16 +385,14 @@
 		settings.save()
 
 		subscription = frappe.new_doc('Subscription')
-		subscription.customer = '_Test Customer'
+		subscription.party_type = 'Customer'
+		subscription.party = '_Test Customer'
 		subscription.append('plans', {'plan': '_Test Plan Name', 'qty': 1})
-		subscription.start = '2018-01-01'
+		subscription.start_date = '2018-01-01'
 		subscription.insert()
 		subscription.process()	# generate first invoice
 		invoices = len(subscription.invoices)
 
-		self.assertEqual(subscription.status, 'Past Due Date')
-		self.assertEqual(len(subscription.invoices), invoices)
-
 		subscription.cancel_subscription()
 		self.assertEqual(subscription.status, 'Cancelled')
 		self.assertEqual(len(subscription.invoices), invoices)
@@ -387,15 +417,14 @@
 		settings.save()
 
 		subscription = frappe.new_doc('Subscription')
-		subscription.customer = '_Test Customer'
+		subscription.party_type = 'Customer'
+		subscription.party = '_Test Customer'
 		subscription.append('plans', {'plan': '_Test Plan Name', 'qty': 1})
-		subscription.start = '2018-01-01'
+		subscription.start_date = '2018-01-01'
 		subscription.insert()
 		subscription.process()		# generate first invoice
 
-		self.assertEqual(subscription.status, 'Past Due Date')
-
-		subscription.process()
+		# Status is unpaid as Days until Due is zero and grace period is Zero
 		self.assertEqual(subscription.status, 'Unpaid')
 
 		subscription.cancel_subscription()
@@ -424,16 +453,14 @@
 		settings.save()
 
 		subscription = frappe.new_doc('Subscription')
-		subscription.customer = '_Test Customer'
+		subscription.party_type = 'Customer'
+		subscription.party = '_Test Customer'
 		subscription.append('plans', {'plan': '_Test Plan Name', 'qty': 1})
-		subscription.start = '2018-01-01'
+		subscription.start_date = '2018-01-01'
 		subscription.insert()
+
 		subscription.process()		# generate first invoice
-
-		self.assertEqual(subscription.status, 'Past Due Date')
-
-		subscription.process()
-		# This should change status to Cancelled since grace period is 0
+		# This should change status to Unpaid since grace period is 0
 		self.assertEqual(subscription.status, 'Unpaid')
 
 		invoice = subscription.get_current_invoice()
@@ -445,7 +472,7 @@
 
 		# A new invoice is generated
 		subscription.process()
-		self.assertEqual(subscription.status, 'Past Due Date')
+		self.assertEqual(subscription.status, 'Unpaid')
 
 		settings.cancel_after_grace = default_grace_period_action
 		settings.save()
@@ -453,7 +480,8 @@
 
 	def test_restart_active_subscription(self):
 		subscription = frappe.new_doc('Subscription')
-		subscription.customer = '_Test Customer'
+		subscription.party_type = 'Customer'
+		subscription.party = '_Test Customer'
 		subscription.append('plans', {'plan': '_Test Plan Name', 'qty': 1})
 		subscription.save()
 
@@ -463,7 +491,8 @@
 
 	def test_subscription_invoice_discount_percentage(self):
 		subscription = frappe.new_doc('Subscription')
-		subscription.customer = '_Test Customer'
+		subscription.party_type = 'Customer'
+		subscription.party = '_Test Customer'
 		subscription.additional_discount_percentage = 10
 		subscription.append('plans', {'plan': '_Test Plan Name', 'qty': 1})
 		subscription.save()
@@ -478,7 +507,8 @@
 
 	def test_subscription_invoice_discount_amount(self):
 		subscription = frappe.new_doc('Subscription')
-		subscription.customer = '_Test Customer'
+		subscription.party_type = 'Customer'
+		subscription.party = '_Test Customer'
 		subscription.additional_discount_amount = 11
 		subscription.append('plans', {'plan': '_Test Plan Name', 'qty': 1})
 		subscription.save()
@@ -495,7 +525,8 @@
 		# Create a non pre-billed subscription, processing should not create
 		# invoices.
 		subscription = frappe.new_doc('Subscription')
-		subscription.customer = '_Test Customer'
+		subscription.party_type = 'Customer'
+		subscription.party = '_Test Customer'
 		subscription.append('plans', {'plan': '_Test Plan Name', 'qty': 1})
 		subscription.save()
 		subscription.process()
@@ -517,10 +548,12 @@
 		settings.save()
 
 		subscription = frappe.new_doc('Subscription')
-		subscription.customer = '_Test Customer'
+		subscription.party_type = 'Customer'
+		subscription.party = '_Test Customer'
 		subscription.generate_invoice_at_period_start = True
 		subscription.append('plans', {'plan': '_Test Plan Name', 'qty': 1})
 		subscription.save()
+		subscription.process()
 		subscription.cancel_subscription()
 
 		self.assertEqual(len(subscription.invoices), 1)
@@ -538,3 +571,65 @@
 		settings.save()
 
 		subscription.delete()
+
+	def test_subscription_with_follow_calendar_months(self):
+		subscription = frappe.new_doc('Subscription')
+		subscription.party_type = 'Supplier'
+		subscription.party = '_Test Supplier'
+		subscription.generate_invoice_at_period_start = 1
+		subscription.follow_calendar_months = 1
+
+		# select subscription start date as '2018-01-15'
+		subscription.start_date = '2018-01-15'
+		subscription.end_date = '2018-07-15'
+		subscription.append('plans', {'plan': '_Test Plan Name 4', 'qty': 1})
+		subscription.save()
+
+		# even though subscription starts at '2018-01-15' and Billing interval is Month and count 3
+		# First invoice will end at '2018-03-31' instead of '2018-04-14'
+		self.assertEqual(get_date_str(subscription.current_invoice_end), '2018-03-31')
+
+	def test_subscription_generate_invoice_past_due(self):
+		subscription = frappe.new_doc('Subscription')
+		subscription.party_type = 'Supplier'
+		subscription.party = '_Test Supplier'
+		subscription.generate_invoice_at_period_start = 1
+		subscription.generate_new_invoices_past_due_date = 1
+		# select subscription start date as '2018-01-15'
+		subscription.start_date = '2018-01-01'
+		subscription.append('plans', {'plan': '_Test Plan Name 4', 'qty': 1})
+		subscription.save()
+
+		# Process subscription and create first invoice
+		# Subscription status will be unpaid since due date has already passed
+		subscription.process()
+		self.assertEqual(len(subscription.invoices), 1)
+		self.assertEqual(subscription.status, 'Unpaid')
+
+		# Now the Subscription is unpaid
+		# Even then new invoice should be created as we have enabled `generate_new_invoices_past_due_date` in
+		# subscription
+
+		subscription.process()
+		self.assertEqual(len(subscription.invoices), 2)
+
+	def test_subscription_without_generate_invoice_past_due(self):
+		subscription = frappe.new_doc('Subscription')
+		subscription.party_type = 'Supplier'
+		subscription.party = '_Test Supplier'
+		subscription.generate_invoice_at_period_start = 1
+		# select subscription start date as '2018-01-15'
+		subscription.start_date = '2018-01-01'
+		subscription.append('plans', {'plan': '_Test Plan Name 4', 'qty': 1})
+		subscription.save()
+
+		# Process subscription and create first invoice
+		# Subscription status will be unpaid since due date has already passed
+		subscription.process()
+		self.assertEqual(len(subscription.invoices), 1)
+		self.assertEqual(subscription.status, 'Unpaid')
+
+		subscription.process()
+		self.assertEqual(len(subscription.invoices), 1)
+
+
diff --git a/erpnext/accounts/doctype/subscription_invoice/subscription_invoice.json b/erpnext/accounts/doctype/subscription_invoice/subscription_invoice.json
index c4bae1d..f54e887 100644
--- a/erpnext/accounts/doctype/subscription_invoice/subscription_invoice.json
+++ b/erpnext/accounts/doctype/subscription_invoice/subscription_invoice.json
@@ -1,73 +1,40 @@
 {
- "allow_copy": 0, 
- "allow_guest_to_view": 0, 
- "allow_import": 0, 
- "allow_rename": 0, 
- "beta": 0, 
- "creation": "2018-02-26 04:21:41.265055", 
- "custom": 0, 
- "docstatus": 0, 
- "doctype": "DocType", 
- "document_type": "", 
- "editable_grid": 1, 
- "engine": "InnoDB", 
+ "actions": [],
+ "creation": "2018-02-26 04:21:41.265055",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "document_type",
+  "invoice"
+ ],
  "fields": [
   {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "invoice", 
-   "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": "Invoice", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Sales Invoice", 
-   "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": "document_type",
+   "fieldtype": "Link",
+   "label": "Document Type ",
+   "options": "DocType",
+   "read_only": 1
+  },
+  {
+   "fieldname": "invoice",
+   "fieldtype": "Dynamic Link",
+   "in_list_view": 1,
+   "label": "Invoice",
+   "options": "document_type",
+   "read_only": 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-02-26 10:48:07.033422", 
- "modified_by": "Administrator", 
- "module": "Accounts", 
- "name": "Subscription Invoice", 
- "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-06-01 22:23:54.462718",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "Subscription Invoice",
+ "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/subscription_plan/subscription_plan.json b/erpnext/accounts/doctype/subscription_plan/subscription_plan.json
index 9f79066..46ce093 100644
--- a/erpnext/accounts/doctype/subscription_plan/subscription_plan.json
+++ b/erpnext/accounts/doctype/subscription_plan/subscription_plan.json
@@ -1,4 +1,5 @@
 {
+ "actions": [],
  "allow_rename": 1,
  "autoname": "field:plan_name",
  "creation": "2018-02-24 11:31:23.066506",
@@ -24,6 +25,7 @@
   "column_break_16",
   "payment_gateway",
   "accounting_dimensions_section",
+  "cost_center",
   "dimension_col_break"
  ],
  "fields": [
@@ -60,8 +62,8 @@
   {
    "fieldname": "price_determination",
    "fieldtype": "Select",
-   "label": "Price Determination",
-   "options": "\nFixed rate\nBased on price list",
+   "label": "Subscription Price Based On",
+   "options": "\nFixed Rate\nBased On Price List\nMonthly Rate",
    "reqd": 1
   },
   {
@@ -69,7 +71,7 @@
    "fieldtype": "Column Break"
   },
   {
-   "depends_on": "eval:doc.price_determination==\"Fixed rate\"",
+   "depends_on": "eval:['Fixed Rate', 'Monthly Rate'].includes(doc.price_determination)",
    "fieldname": "cost",
    "fieldtype": "Currency",
    "in_list_view": 1,
@@ -136,9 +138,16 @@
   {
    "fieldname": "dimension_col_break",
    "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "cost_center",
+   "fieldtype": "Link",
+   "label": "Cost Center",
+   "options": "Cost Center"
   }
  ],
- "modified": "2019-07-25 18:35:04.362556",
+ "links": [],
+ "modified": "2020-06-25 10:53:44.205774",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "Subscription Plan",
@@ -155,6 +164,30 @@
    "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
   }
  ],
  "sort_field": "modified",
diff --git a/erpnext/accounts/doctype/subscription_plan/subscription_plan.py b/erpnext/accounts/doctype/subscription_plan/subscription_plan.py
index 625979b..1ca442a 100644
--- a/erpnext/accounts/doctype/subscription_plan/subscription_plan.py
+++ b/erpnext/accounts/doctype/subscription_plan/subscription_plan.py
@@ -5,6 +5,7 @@
 from __future__ import unicode_literals
 import frappe
 from frappe import _
+from frappe.utils import get_first_day, get_last_day, date_diff, flt, getdate
 from frappe.model.document import Document
 from erpnext.utilities.product import get_price
 
@@ -17,12 +18,12 @@
 			frappe.throw(_('Billing Interval Count cannot be less than 1'))
 
 @frappe.whitelist()
-def get_plan_rate(plan, quantity=1, customer=None):
+def get_plan_rate(plan, quantity=1, customer=None, start_date=None, end_date=None, prorate_factor=1):
 	plan = frappe.get_doc("Subscription Plan", plan)
-	if plan.price_determination == "Fixed rate":
-		return plan.cost
+	if plan.price_determination == "Fixed Rate":
+		return plan.cost * prorate_factor
 
-	elif plan.price_determination == "Based on price list":
+	elif plan.price_determination == "Based On Price List":
 		if customer:
 			customer_group = frappe.db.get_value("Customer", customer, "customer_group")
 		else:
@@ -32,4 +33,25 @@
 		if not price:
 			return 0
 		else:
-			return price.price_list_rate
+			return price.price_list_rate * prorate_factor
+
+	elif plan.price_determination == 'Monthly Rate':
+		start_date = getdate(start_date)
+		end_date = getdate(end_date)
+
+		no_of_months = (end_date.year - start_date.year) * 12 + (end_date.month - start_date.month) + 1
+		cost = plan.cost * no_of_months
+
+		# Adjust cost if start or end date is not month start or end
+		prorate = frappe.db.get_single_value('Subscription Settings', 'prorate')
+
+		if prorate:
+			prorate_factor = flt(date_diff(start_date, get_first_day(start_date)) / date_diff(
+				get_last_day(start_date), get_first_day(start_date)), 1)
+
+			prorate_factor += flt(date_diff(get_last_day(end_date), end_date) / date_diff(
+				get_last_day(end_date), get_first_day(end_date)), 1)
+
+			cost -= (plan.cost * prorate_factor)
+
+		return cost
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/subscription_plan_detail/subscription_plan_detail.json b/erpnext/accounts/doctype/subscription_plan_detail/subscription_plan_detail.json
index ca54a16..3e16303 100644
--- a/erpnext/accounts/doctype/subscription_plan_detail/subscription_plan_detail.json
+++ b/erpnext/accounts/doctype/subscription_plan_detail/subscription_plan_detail.json
@@ -1,106 +1,40 @@
 {
- "allow_copy": 0, 
- "allow_guest_to_view": 0, 
- "allow_import": 0, 
- "allow_rename": 0, 
- "beta": 0, 
- "creation": "2018-02-25 07:35:07.736146", 
- "custom": 0, 
- "docstatus": 0, 
- "doctype": "DocType", 
- "document_type": "", 
- "editable_grid": 1, 
- "engine": "InnoDB", 
+ "actions": [],
+ "creation": "2018-02-25 07:35:07.736146",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "plan",
+  "qty"
+ ],
  "fields": [
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "qty", 
-   "fieldtype": "Int", 
-   "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": "Quantity", 
-   "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": "qty",
+   "fieldtype": "Int",
+   "in_list_view": 1,
+   "label": "Quantity",
+   "reqd": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "plan", 
-   "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": "Plan", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Subscription Plan", 
-   "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": "plan",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "label": "Plan",
+   "options": "Subscription Plan",
+   "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-06-20 15:35:13.514699", 
- "modified_by": "Administrator", 
- "module": "Accounts", 
- "name": "Subscription Plan Detail", 
- "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-06-14 17:44:05.275100",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "Subscription Plan Detail",
+ "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/subscription_settings/subscription_settings.json b/erpnext/accounts/doctype/subscription_settings/subscription_settings.json
index 8c7c6f3..821db7e 100644
--- a/erpnext/accounts/doctype/subscription_settings/subscription_settings.json
+++ b/erpnext/accounts/doctype/subscription_settings/subscription_settings.json
@@ -1,179 +1,76 @@
 {
- "allow_copy": 0, 
- "allow_guest_to_view": 0, 
- "allow_import": 0, 
- "allow_rename": 0, 
- "beta": 0, 
- "creation": "2018-02-26 06:13:37.910139", 
- "custom": 0, 
- "docstatus": 0, 
- "doctype": "DocType", 
- "document_type": "", 
- "editable_grid": 1, 
- "engine": "InnoDB", 
+ "actions": [],
+ "creation": "2018-02-26 06:13:37.910139",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "grace_period",
+  "cancel_after_grace",
+  "prorate"
+ ],
  "fields": [
   {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "default": "1", 
-   "description": "Number of days after invoice date has elapsed before canceling subscription or marking subscription as unpaid", 
-   "fieldname": "grace_period", 
-   "fieldtype": "Int", 
-   "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": "Grace Period", 
-   "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
-  }, 
+   "default": "1",
+   "description": "Number of days after invoice date has elapsed before canceling subscription or marking subscription as unpaid",
+   "fieldname": "grace_period",
+   "fieldtype": "Int",
+   "label": "Grace Period"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "default": "0", 
-   "fieldname": "cancel_after_grace", 
-   "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": "Cancel Invoice After Grace Period", 
-   "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
-  }, 
+   "default": "0",
+   "fieldname": "cancel_after_grace",
+   "fieldtype": "Check",
+   "label": "Cancel Subscription After Grace Period"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "default": "1", 
-   "fieldname": "prorate", 
-   "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": "Prorate", 
-   "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
+   "default": "1",
+   "fieldname": "prorate",
+   "fieldtype": "Check",
+   "label": "Prorate"
   }
- ], 
- "has_web_view": 0, 
- "hide_heading": 0, 
- "hide_toolbar": 0, 
- "idx": 0, 
- "image_view": 0, 
- "in_create": 0, 
- "is_submittable": 0, 
- "issingle": 1, 
- "istable": 0, 
- "max_attachments": 0, 
- "modified": "2018-02-26 13:58:09.455832", 
- "modified_by": "Administrator", 
- "module": "Accounts", 
- "name": "Subscription Settings", 
- "name_case": "", 
- "owner": "Administrator", 
+ ],
+ "issingle": 1,
+ "links": [],
+ "modified": "2020-06-23 09:13:44.292792",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "Subscription Settings",
+ "owner": "Administrator",
  "permissions": [
   {
-   "amend": 0, 
-   "apply_user_permissions": 0, 
-   "cancel": 0, 
-   "create": 1, 
-   "delete": 1, 
-   "email": 1, 
-   "export": 0, 
-   "if_owner": 0, 
-   "import": 0, 
-   "permlevel": 0, 
-   "print": 1, 
-   "read": 1, 
-   "report": 0, 
-   "role": "System Manager", 
-   "set_user_permissions": 0, 
-   "share": 1, 
-   "submit": 0, 
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "print": 1,
+   "read": 1,
+   "role": "System Manager",
+   "share": 1,
    "write": 1
-  }, 
+  },
   {
-   "amend": 0, 
-   "apply_user_permissions": 0, 
-   "cancel": 0, 
-   "create": 1, 
-   "delete": 1, 
-   "email": 1, 
-   "export": 0, 
-   "if_owner": 0, 
-   "import": 0, 
-   "permlevel": 0, 
-   "print": 1, 
-   "read": 1, 
-   "report": 0, 
-   "role": "Administrator", 
-   "set_user_permissions": 0, 
-   "share": 1, 
-   "submit": 0, 
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "print": 1,
+   "read": 1,
+   "role": "Accounts Manager",
+   "share": 1,
+   "write": 1
+  },
+  {
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "print": 1,
+   "read": 1,
+   "role": "Accounts User",
+   "share": 1,
    "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
+ ],
+ "quick_entry": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
 }
\ No newline at end of file
diff --git a/erpnext/accounts/general_ledger.py b/erpnext/accounts/general_ledger.py
index bfe35ab..a245d63 100644
--- a/erpnext/accounts/general_ledger.py
+++ b/erpnext/accounts/general_ledger.py
@@ -140,10 +140,8 @@
 	gle = frappe.new_doc("GL Entry")
 	gle.update(args)
 	gle.flags.ignore_permissions = 1
-	gle.validate()
-	gle.db_insert()
+	gle.insert()
 	gle.run_method("on_update_with_args", adv_adj, update_outstanding)
-	gle.flags.ignore_validate = True
 	gle.submit()
 
 	# check against budget
diff --git a/erpnext/accounts/module_onboarding/accounts/accounts.json b/erpnext/accounts/module_onboarding/accounts/accounts.json
index 12da440..ba1a779 100644
--- a/erpnext/accounts/module_onboarding/accounts/accounts.json
+++ b/erpnext/accounts/module_onboarding/accounts/accounts.json
@@ -13,7 +13,7 @@
  "documentation_url": "https://docs.erpnext.com/docs/user/manual/en/accounts",
  "idx": 0,
  "is_complete": 0,
- "modified": "2020-05-14 22:11:06.475938",
+ "modified": "2020-07-08 14:06:09.033880",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "Accounts",
@@ -44,8 +44,7 @@
    "step": "Configure Account Settings"
   }
  ],
- "subtitle": "Accounts, invoices and taxation.",
- "success_message": "The Accounts module is now set up!",
- "title": "Let's Setup Your Accounts and Taxes.",
- "user_can_dismiss": 1
+ "subtitle": "Accounts, Invoices, Taxation, and more.",
+ "success_message": "The Accounts Module is all set up!",
+ "title": "Let's Set Up Your Accounts and Taxes."
 }
\ No newline at end of file
diff --git a/erpnext/accounts/number_card/total_incoming_bills/total_incoming_bills.json b/erpnext/accounts/number_card/total_incoming_bills/total_incoming_bills.json
new file mode 100644
index 0000000..283e187
--- /dev/null
+++ b/erpnext/accounts/number_card/total_incoming_bills/total_incoming_bills.json
@@ -0,0 +1,21 @@
+{
+ "aggregate_function_based_on": "base_net_total",
+ "creation": "2020-07-17 11:25:34.748329",
+ "docstatus": 0,
+ "doctype": "Number Card",
+ "document_type": "Purchase Invoice",
+ "filters_json": "[[\"Purchase Invoice\",\"docstatus\",\"=\",\"1\",false],[\"Purchase Invoice\",\"posting_date\",\"Timespan\",\"this year\",false]]",
+ "function": "Sum",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "label": "Total Incoming Bills",
+ "modified": "2020-07-22 13:06:46.045344",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "Total Incoming Bills",
+ "owner": "Administrator",
+ "show_percentage_stats": 1,
+ "stats_time_interval": "Monthly",
+ "type": "Document Type"
+}
\ No newline at end of file
diff --git a/erpnext/accounts/number_card/total_incoming_payment/total_incoming_payment.json b/erpnext/accounts/number_card/total_incoming_payment/total_incoming_payment.json
new file mode 100644
index 0000000..bc23c15
--- /dev/null
+++ b/erpnext/accounts/number_card/total_incoming_payment/total_incoming_payment.json
@@ -0,0 +1,21 @@
+{
+ "aggregate_function_based_on": "base_received_amount",
+ "creation": "2020-07-17 11:25:34.673195",
+ "docstatus": 0,
+ "doctype": "Number Card",
+ "document_type": "Payment Entry",
+ "filters_json": "[[\"Payment Entry\",\"docstatus\",\"=\",\"1\",false],[\"Payment Entry\",\"posting_date\",\"Timespan\",\"this year\",false],[\"Payment Entry\",\"payment_type\",\"=\",\"Receive\",false]]",
+ "function": "Sum",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "label": "Total Incoming Payment",
+ "modified": "2020-07-22 13:06:20.237689",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "Total Incoming Payment",
+ "owner": "Administrator",
+ "show_percentage_stats": 1,
+ "stats_time_interval": "Monthly",
+ "type": "Document Type"
+}
\ No newline at end of file
diff --git a/erpnext/accounts/number_card/total_outgoing_bills/total_outgoing_bills.json b/erpnext/accounts/number_card/total_outgoing_bills/total_outgoing_bills.json
new file mode 100644
index 0000000..fe91618
--- /dev/null
+++ b/erpnext/accounts/number_card/total_outgoing_bills/total_outgoing_bills.json
@@ -0,0 +1,21 @@
+{
+ "aggregate_function_based_on": "base_net_total",
+ "creation": "2020-07-17 11:25:34.725416",
+ "docstatus": 0,
+ "doctype": "Number Card",
+ "document_type": "Sales Invoice",
+ "filters_json": "[[\"Sales Invoice\",\"docstatus\",\"=\",\"1\",false],[\"Sales Invoice\",\"posting_date\",\"Timespan\",\"this year\",false]]",
+ "function": "Sum",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "label": "Total Outgoing Bills",
+ "modified": "2020-07-22 13:07:19.633101",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "Total Outgoing Bills",
+ "owner": "Administrator",
+ "show_percentage_stats": 1,
+ "stats_time_interval": "Monthly",
+ "type": "Document Type"
+}
\ No newline at end of file
diff --git a/erpnext/accounts/number_card/total_outgoing_payment/total_outgoing_payment.json b/erpnext/accounts/number_card/total_outgoing_payment/total_outgoing_payment.json
new file mode 100644
index 0000000..d27be88
--- /dev/null
+++ b/erpnext/accounts/number_card/total_outgoing_payment/total_outgoing_payment.json
@@ -0,0 +1,21 @@
+{
+ "aggregate_function_based_on": "base_paid_amount",
+ "creation": "2020-07-17 11:25:34.700137",
+ "docstatus": 0,
+ "doctype": "Number Card",
+ "document_type": "Payment Entry",
+ "filters_json": "[[\"Payment Entry\",\"docstatus\",\"=\",\"1\",false],[\"Payment Entry\",\"posting_date\",\"Timespan\",\"this year\",false],[\"Payment Entry\",\"payment_type\",\"=\",\"Pay\",false]]",
+ "function": "Sum",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "label": "Total Outgoing Payment",
+ "modified": "2020-07-22 12:49:34.942896",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "Total Outgoing Payment",
+ "owner": "Administrator",
+ "show_percentage_stats": 1,
+ "stats_time_interval": "Monthly",
+ "type": "Document Type"
+}
\ No newline at end of file
diff --git a/erpnext/accounts/onboarding_step/create_a_customer/create_a_customer.json b/erpnext/accounts/onboarding_step/create_a_customer/create_a_customer.json
index bb396d2..5a403b0 100644
--- a/erpnext/accounts/onboarding_step/create_a_customer/create_a_customer.json
+++ b/erpnext/accounts/onboarding_step/create_a_customer/create_a_customer.json
@@ -8,7 +8,7 @@
  "is_mandatory": 0,
  "is_single": 0,
  "is_skipped": 0,
- "modified": "2020-05-14 17:46:41.831517",
+ "modified": "2020-06-01 13:16:19.731719",
  "modified_by": "Administrator",
  "name": "Create a Customer",
  "owner": "Administrator",
diff --git a/erpnext/accounts/onboarding_step/create_a_product/create_a_product.json b/erpnext/accounts/onboarding_step/create_a_product/create_a_product.json
index 450bee1..d2068e1 100644
--- a/erpnext/accounts/onboarding_step/create_a_product/create_a_product.json
+++ b/erpnext/accounts/onboarding_step/create_a_product/create_a_product.json
@@ -1,6 +1,6 @@
 {
  "action": "Create Entry",
- "creation": "2020-05-14 17:45:28.554605",
+ "creation": "2020-05-12 18:16:06.624554",
  "docstatus": 0,
  "doctype": "Onboarding Step",
  "idx": 0,
@@ -8,7 +8,7 @@
  "is_mandatory": 0,
  "is_single": 0,
  "is_skipped": 0,
- "modified": "2020-05-14 17:45:28.554605",
+ "modified": "2020-05-12 18:30:02.489949",
  "modified_by": "Administrator",
  "name": "Create a Product",
  "owner": "Administrator",
diff --git a/erpnext/accounts/page/bank_reconciliation/bank_reconciliation.py b/erpnext/accounts/page/bank_reconciliation/bank_reconciliation.py
index 69f9907..7df090b 100644
--- a/erpnext/accounts/page/bank_reconciliation/bank_reconciliation.py
+++ b/erpnext/accounts/page/bank_reconciliation/bank_reconciliation.py
@@ -21,7 +21,7 @@
 	if payment_doctype == "Payment Entry" and payment_entry.unallocated_amount > transaction.unallocated_amount:
 		frappe.throw(_("The unallocated amount of Payment Entry {0} \
 			is greater than the Bank Transaction's unallocated amount").format(payment_name))
-		
+
 	if transaction.unallocated_amount == 0:
 		frappe.throw(_("This bank transaction is already fully reconciled"))
 
@@ -289,6 +289,7 @@
 	else:
 		return []
 
+@frappe.whitelist()
 def payment_entry_query(doctype, txt, searchfield, start, page_len, filters):
 	account = frappe.db.get_value("Bank Account", filters.get("bank_account"), "account")
 	if not account:
@@ -317,6 +318,7 @@
 		}
 	)
 
+@frappe.whitelist()
 def journal_entry_query(doctype, txt, searchfield, start, page_len, filters):
 	account = frappe.db.get_value("Bank Account", filters.get("bank_account"), "account")
 
@@ -352,6 +354,7 @@
 		}
 	)
 
+@frappe.whitelist()
 def sales_invoices_query(doctype, txt, searchfield, start, page_len, filters):
 	return frappe.db.sql("""
 		SELECT
diff --git a/erpnext/accounts/page/pos/pos.js b/erpnext/accounts/page/pos/pos.js
deleted file mode 100755
index 24fcb41..0000000
--- a/erpnext/accounts/page/pos/pos.js
+++ /dev/null
@@ -1,2105 +0,0 @@
-frappe.provide("erpnext.pos");
-{% include "erpnext/public/js/controllers/taxes_and_totals.js" %}
-
-frappe.pages['pos'].on_page_load = function (wrapper) {
-	var page = frappe.ui.make_app_page({
-		parent: wrapper,
-		title: __('Point of Sale'),
-		single_column: true
-	});
-
-	frappe.db.get_value('POS Settings', {name: 'POS Settings'}, 'is_online', (r) => {
-		if (r && r.use_pos_in_offline_mode && cint(r.use_pos_in_offline_mode)) {
-			// offline
-			wrapper.pos = new erpnext.pos.PointOfSale(wrapper);
-			cur_pos = wrapper.pos;
-		} else {
-			// online
-			frappe.flags.is_online = true
-			frappe.set_route('point-of-sale');
-		}
-	});
-}
-
-frappe.pages['pos'].refresh = function (wrapper) {
-	window.onbeforeunload = function () {
-		return wrapper.pos.beforeunload()
-	}
-
-	if (frappe.flags.is_online) {
-		frappe.set_route('point-of-sale');
-	}
-}
-
-erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
-	init: function (wrapper) {
-		this.page_len = 20;
-		this.freeze = false;
-		this.page = wrapper.page;
-		this.wrapper = $(wrapper).find('.page-content');
-		this.set_indicator();
-		this.onload();
-		this.make_menu_list();
-		this.bind_events();
-		this.bind_items_event();
-		this.si_docs = this.get_doc_from_localstorage();
-	},
-
-	beforeunload: function (e) {
-		if (this.connection_status == false && frappe.get_route()[0] == "pos") {
-			e = e || window.event;
-
-			// For IE and Firefox prior to version 4
-			if (e) {
-				e.returnValue = __("You are in offline mode. You will not be able to reload until you have network.");
-				return
-			}
-
-			// For Safari
-			return __("You are in offline mode. You will not be able to reload until you have network.");
-		}
-	},
-
-	check_internet_connection: function () {
-		var me = this;
-		//Check Internet connection after every 30 seconds
-		setInterval(function () {
-			me.set_indicator();
-		}, 5000)
-	},
-
-	set_indicator: function () {
-		var me = this;
-		// navigator.onLine
-		this.connection_status = false;
-		this.page.set_indicator(__("Offline"), "grey")
-		frappe.call({
-			method: "frappe.handler.ping",
-			callback: function (r) {
-				if (r.message) {
-					me.connection_status = true;
-					me.page.set_indicator(__("Online"), "green")
-				}
-			}
-		})
-	},
-
-	onload: function () {
-		var me = this;
-		this.get_data_from_server(function () {
-			me.make_control();
-			me.create_new();
-			me.make();
-		});
-	},
-
-	make_menu_list: function () {
-		var me = this;
-		this.page.clear_menu();
-
-		// for mobile
-		this.page.add_menu_item(__("Pay"), function () {
-			me.validate();
-			me.update_paid_amount_status(true);
-			me.create_invoice();
-			me.make_payment();
-		}).addClass('visible-xs');
-
-		this.page.add_menu_item(__("New Sales Invoice"), function () {
-			me.save_previous_entry();
-			me.create_new();
-		})
-
-		this.page.add_menu_item(__("Sync Master Data"), function () {
-			me.get_data_from_server(function () {
-				me.load_data(false);
-				me.make_item_list();
-				me.set_missing_values();
-			})
-		});
-
-		this.page.add_menu_item(__("Sync Offline Invoices"), function () {
-			me.freeze_screen = true;
-			me.sync_sales_invoice()
-		});
-
-		this.page.add_menu_item(__("Cashier Closing"), function () {
-			frappe.set_route('List', 'Cashier Closing');
-		});
-
-		this.page.add_menu_item(__("POS Profile"), function () {
-			frappe.set_route('List', 'POS Profile');
-		});
-	},
-
-	email_prompt: function() {
-		var me = this;
-		var fields = [{label:__("To"), fieldtype:"Data", reqd: 0, fieldname:"recipients",length:524288},
-			{fieldtype: "Section Break", collapsible: 1, label: "CC & Email Template"},
-			{fieldtype: "Section Break"},
-			{label:__("Subject"), fieldtype:"Data", reqd: 1,
-				fieldname:"subject",length:524288},
-			{fieldtype: "Section Break"},
-			{label:__("Message"), fieldtype:"Text Editor", reqd: 1,
-				fieldname:"content"},
-			{fieldtype: "Section Break"},
-			{fieldtype: "Column Break"}];
-
-		this.email_dialog = new frappe.ui.Dialog({
-			title: "Email",
-			fields: fields,
-			primary_action_label: __("Send"),
-			primary_action: function() {
-				me.send_action();
-			}
-		});
-
-		this.email_dialog.show()
-	},
-
-	send_action: function() {
-		this.email_queue = this.get_email_queue()
-		this.email_queue[this.frm.doc.offline_pos_name] = JSON.stringify(this.email_dialog.get_values())
-		this.update_email_queue()
-		this.email_dialog.hide()
-	},
-
-	update_email_queue: function () {
-		try {
-			localStorage.setItem('email_queue', JSON.stringify(this.email_queue));
-		} catch (e) {
-			frappe.throw(__("LocalStorage is full, did not save"))
-		}
-	},
-
-	get_email_queue: function () {
-		try {
-			return JSON.parse(localStorage.getItem('email_queue')) || {};
-		} catch (e) {
-			return {}
-		}
-	},
-
-	get_customers_details: function () {
-		try {
-			return JSON.parse(localStorage.getItem('customer_details')) || {};
-		} catch (e) {
-			return {}
-		}
-	},
-
-	edit_record: function () {
-		var me = this;
-
-		doc_data = this.get_invoice_doc(this.si_docs);
-		if (doc_data) {
-			this.frm.doc = doc_data[0][this.frm.doc.offline_pos_name];
-			this.set_missing_values();
-			this.refresh(false);
-			this.toggle_input_field();
-			this.list_dialog && this.list_dialog.hide();
-		}
-	},
-
-	delete_records: function () {
-		var me = this;
-		this.validate_list()
-		this.remove_doc_from_localstorage()
-		this.update_localstorage();
-		this.toggle_delete_button();
-	},
-
-	validate_list: function() {
-		var me = this;
-		this.si_docs = this.get_submitted_invoice()
-		$.each(this.removed_items, function(index, pos_name){
-			$.each(me.si_docs, function(key, data){
-				if(me.si_docs[key][pos_name] && me.si_docs[key][pos_name].offline_pos_name == pos_name ){
-					frappe.throw(__("Submitted orders can not be deleted"))
-				}
-			})
-		})
-	},
-
-	toggle_delete_button: function () {
-		var me = this;
-		if(this.pos_profile_data["allow_delete"]) {
-			if (this.removed_items && this.removed_items.length > 0) {
-				$(this.page.wrapper).find('.btn-danger').show();
-			} else {
-				$(this.page.wrapper).find('.btn-danger').hide();
-			}
-		}
-	},
-
-	get_doctype_status: function (doc) {
-		if (doc.docstatus == 0) {
-			return { status: "Draft", indicator: "red" }
-		} else if (doc.outstanding_amount == 0) {
-			return { status: "Paid", indicator: "green" }
-		} else {
-			return { status: "Submitted", indicator: "blue" }
-		}
-	},
-
-	set_missing_values: function () {
-		var me = this;
-		doc = JSON.parse(localStorage.getItem('doc'))
-		if (this.frm.doc.payments.length == 0) {
-			this.frm.doc.payments = doc.payments;
-			this.calculate_outstanding_amount();
-		}
-
-		this.set_customer_value_in_party_field();
-
-		if (!this.frm.doc.write_off_account) {
-			this.frm.doc.write_off_account = doc.write_off_account
-		}
-
-		if (!this.frm.doc.account_for_change_amount) {
-			this.frm.doc.account_for_change_amount = doc.account_for_change_amount
-		}
-	},
-
-	set_customer_value_in_party_field: function() {
-		if (this.frm.doc.customer) {
-			this.party_field.$input.val(this.frm.doc.customer);
-		}
-	},
-
-	get_invoice_doc: function (si_docs) {
-		var me = this;
-		this.si_docs = this.get_doc_from_localstorage();
-
-		return $.grep(this.si_docs, function (data) {
-			for (key in data) {
-				return key == me.frm.doc.offline_pos_name;
-			}
-		})
-	},
-
-	get_data_from_server: function (callback) {
-		var me = this;
-		frappe.call({
-			method: "erpnext.accounts.doctype.sales_invoice.pos.get_pos_data",
-			freeze: true,
-			freeze_message: __("Master data syncing, it might take some time"),
-			callback: function (r) {
-				localStorage.setItem('doc', JSON.stringify(r.message.doc));
-				me.init_master_data(r)
-				me.set_interval_for_si_sync();
-				me.check_internet_connection();
-				if (callback) {
-					callback();
-				}
-			},
-			error: () => {
-				setTimeout(() => frappe.set_route('List', 'POS Profile'), 2000);
-			}
-		})
-	},
-
-	init_master_data: function (r) {
-		var me = this;
-		this.doc = JSON.parse(localStorage.getItem('doc'));
-		this.meta = r.message.meta;
-		this.item_data = r.message.items;
-		this.item_groups = r.message.item_groups;
-		this.customers = r.message.customers;
-		this.serial_no_data = r.message.serial_no_data;
-		this.batch_no_data = r.message.batch_no_data;
-		this.barcode_data = r.message.barcode_data;
-		this.tax_data = r.message.tax_data;
-		this.contacts = r.message.contacts;
-		this.address = r.message.address || {};
-		this.price_list_data = r.message.price_list_data;
-		this.customer_wise_price_list = r.message.customer_wise_price_list
-		this.bin_data = r.message.bin_data;
-		this.pricing_rules = r.message.pricing_rules;
-		this.print_template = r.message.print_template;
-		this.pos_profile_data = r.message.pos_profile;
-		this.default_customer = r.message.default_customer || null;
-		this.print_settings = locals[":Print Settings"]["Print Settings"];
-		this.letter_head = (this.pos_profile_data.length > 0) ? frappe.boot.letter_heads[this.pos_profile_data[letter_head]] : {};
-	},
-
-	save_previous_entry: function () {
-		if (this.frm.doc.docstatus < 1 && this.frm.doc.items.length > 0) {
-			this.create_invoice();
-		}
-	},
-
-	create_new: function () {
-		var me = this;
-		this.frm = {}
-		this.load_data(true);
-		this.frm.doc.offline_pos_name = '';
-		this.setup();
-		this.set_default_customer()
-	},
-
-	load_data: function (load_doc) {
-		var me = this;
-
-		this.items = this.item_data;
-		this.actual_qty_dict = {};
-
-		if (load_doc) {
-			this.frm.doc = JSON.parse(localStorage.getItem('doc'));
-		}
-
-		$.each(this.meta, function (i, data) {
-			frappe.meta.sync(data)
-			locals["DocType"][data.name] = data;
-		})
-
-		this.print_template_data = frappe.render_template("print_template", {
-			content: this.print_template,
-			title: "POS",
-			base_url: frappe.urllib.get_base_url(),
-			print_css: frappe.boot.print_css,
-			print_settings: this.print_settings,
-			header: this.letter_head.header,
-			footer: this.letter_head.footer,
-			landscape: false,
-			columns: []
-		})
-	},
-
-	setup: function () {
-		this.set_primary_action();
-		this.party_field.$input.attr('disabled', false);
-		if(this.selected_row) {
-			this.selected_row.hide()
-		}
-	},
-
-	set_default_customer: function() {
-		if (this.default_customer && !this.frm.doc.customer) {
-			this.party_field.$input.val(this.default_customer);
-			this.frm.doc.customer = this.default_customer;
-			this.numeric_keypad.show();
-			this.toggle_list_customer(false)
-			this.toggle_item_cart(true)
-		}
-	},
-
-	set_transaction_defaults: function (party) {
-		var me = this;
-		this.party = party;
-		this.price_list = (party == "Customer" ?
-			this.frm.doc.selling_price_list : this.frm.doc.buying_price_list);
-		this.price_list_field = (party == "Customer" ? "selling_price_list" : "buying_price_list");
-		this.sales_or_purchase = (party == "Customer" ? "Sales" : "Purchase");
-	},
-
-	make: function () {
-		this.make_item_list();
-		this.make_discount_field()
-	},
-
-	make_control: function() {
-		this.frm = {}
-		this.frm.doc = this.doc
-		this.set_transaction_defaults("Customer");
-		this.frm.doc["allow_user_to_edit_rate"] = this.pos_profile_data["allow_user_to_edit_rate"] ? true : false;
-		this.frm.doc["allow_user_to_edit_discount"] = this.pos_profile_data["allow_user_to_edit_discount"] ? true : false;
-		this.wrapper.html(frappe.render_template("pos", this.frm.doc));
-		this.make_search();
-		this.make_customer();
-		this.make_list_customers();
-		this.bind_numeric_keypad();
-	},
-
-	make_search: function () {
-		var me = this;
-		this.search_item = frappe.ui.form.make_control({
-			df: {
-				"fieldtype": "Data",
-				"label": __("Item"),
-				"fieldname": "pos_item",
-				"placeholder": __("Search Item")
-			},
-			parent: this.wrapper.find(".search-item"),
-			only_input: true,
-		});
-
-		this.search_item.make_input();
-
-		this.search_item.$input.on("keypress", function (event) {
-
-			clearTimeout(me.last_search_timeout);
-			me.last_search_timeout = setTimeout(() => {
-				if((me.search_item.$input.val() != "") || (event.which == 13)) {
-					me.items = me.get_items();
-					me.make_item_list();
-				}
-			}, 400);
-		});
-
-		this.search_item_group = this.wrapper.find('.search-item-group');
-		sorted_item_groups = this.get_sorted_item_groups()
-		var dropdown_html = sorted_item_groups.map(function(item_group) {
-			return "<li><a class='option' data-value='"+item_group+"'>"+item_group+"</a></li>";
-		}).join("");
-
-		this.search_item_group.find('.dropdown-menu').html(dropdown_html);
-
-		this.search_item_group.on('click', '.dropdown-menu a', function() {
-			me.selected_item_group = $(this).attr('data-value');
-			me.search_item_group.find('.dropdown-text').text(me.selected_item_group);
-
-			me.page_len = 20;
-			me.items = me.get_items();
-			me.make_item_list();
-		})
-
-		me.toggle_more_btn();
-
-		this.wrapper.on("click", ".btn-more", function() {
-			me.page_len += 20;
-			me.items = me.get_items();
-			me.make_item_list();
-			me.toggle_more_btn();
-		});
-
-		this.page.wrapper.on("click", ".edit-customer-btn", function() {
-			me.update_customer()
-		})
-	},
-
-	get_sorted_item_groups: function() {
-		list = {}
-		$.each(this.item_groups, function(i, data) {
-			list[i] = data[0]
-		})
-
-		return Object.keys(list).sort(function(a,b){return list[a]-list[b]})
-	},
-
-	toggle_more_btn: function() {
-		if(!this.items || this.items.length <= this.page_len) {
-			this.wrapper.find(".btn-more").hide();
-		} else {
-			this.wrapper.find(".btn-more").show();
-		}
-	},
-
-	toggle_totals_area: function(show) {
-
-		if(show === undefined) {
-			show = this.is_totals_area_collapsed;
-		}
-
-		var totals_area = this.wrapper.find('.totals-area');
-		totals_area.find('.net-total-area, .tax-area, .discount-amount-area')
-			.toggle(show);
-
-		if(show) {
-			totals_area.find('.collapse-btn i')
-				.removeClass('octicon-chevron-down')
-				.addClass('octicon-chevron-up');
-		} else {
-			totals_area.find('.collapse-btn i')
-				.removeClass('octicon-chevron-up')
-				.addClass('octicon-chevron-down');
-		}
-
-		this.is_totals_area_collapsed = !show;
-	},
-
-	make_list_customers: function () {
-		var me = this;
-		this.list_customers_btn = this.page.wrapper.find('.list-customers-btn');
-		this.add_customer_btn = this.wrapper.find('.add-customer-btn');
-		this.pos_bill = this.wrapper.find('.pos-bill-wrapper').hide();
-		this.list_customers = this.wrapper.find('.list-customers');
-		this.numeric_keypad = this.wrapper.find('.numeric_keypad');
-		this.list_customers_btn.addClass("view_customer")
-
-		me.render_list_customers();
-		me.toggle_totals_area(false);
-
-		this.page.wrapper.on('click', '.list-customers-btn', function() {
-			$(this).toggleClass("view_customer");
-			if($(this).hasClass("view_customer")) {
-				me.render_list_customers();
-				me.list_customers.show();
-				me.pos_bill.hide();
-				me.numeric_keypad.hide();
-				me.toggle_delete_button()
-			} else {
-				if(me.frm.doc.docstatus == 0) {
-					me.party_field.$input.attr('disabled', false);
-				}
-				me.pos_bill.show();
-				me.toggle_totals_area(false);
-				me.toggle_delete_button()
-				me.list_customers.hide();
-				me.numeric_keypad.show();
-			}
-		});
-		this.add_customer_btn.on('click', function() {
-			me.save_previous_entry();
-			me.create_new();
-			me.refresh();
-			me.set_focus();
-		});
-		this.pos_bill.on('click', '.collapse-btn', function() {
-			me.toggle_totals_area();
-		});
-	},
-
-	bind_numeric_keypad: function() {
-		var me = this;
-		$(this.numeric_keypad).find('.pos-operation').on('click', function(){
-			me.numeric_val = '';
-		})
-
-		$(this.numeric_keypad).find('.numeric-keypad').on('click', function(){
-			me.numeric_id = $(this).attr("id") || me.numeric_id;
-			me.val = $(this).attr("val")
-			if(me.numeric_id) {
-				me.selected_field = $(me.wrapper).find('.selected-item').find('.' + me.numeric_id)
-			}
-
-			if(me.val && me.numeric_id) {
-				me.numeric_val += me.val;
-				me.selected_field.val(flt(me.numeric_val))
-				me.selected_field.trigger("change")
-				// me.render_selected_item()
-			}
-
-			if(me.numeric_id && $(this).hasClass('pos-operation')) {
-				me.numeric_keypad.find('button.pos-operation').removeClass('active');
-				$(this).addClass('active');
-
-				me.selected_row.find('.pos-list-row').removeClass('active');
-				me.selected_field.closest('.pos-list-row').addClass('active');
-			}
-		})
-
-		$(this.numeric_keypad).find('.numeric-del').click(function(){
-			if(me.numeric_id) {
-				me.selected_field = $(me.wrapper).find('.selected-item').find('.' + me.numeric_id)
-				me.numeric_val = cstr(flt(me.selected_field.val())).slice(0, -1);
-				me.selected_field.val(me.numeric_val);
-				me.selected_field.trigger("change")
-			} else {
-				//Remove an item from the cart, if focus is at selected item
-				me.remove_selected_item()
-			}
-		})
-
-		$(this.numeric_keypad).find('.pos-pay').click(function(){
-			me.validate();
-			me.update_paid_amount_status(true);
-			me.create_invoice();
-			me.make_payment();
-		})
-	},
-
-	remove_selected_item: function() {
-		this.remove_item = []
-		idx = $(this.wrapper).find(".pos-selected-item-action").attr("data-idx")
-		this.remove_item.push(idx)
-		this.remove_zero_qty_items_from_cart()
-		this.update_paid_amount_status(false)
-	},
-
-	render_list_customers: function () {
-		var me = this;
-
-		this.removed_items = [];
-		// this.list_customers.empty();
-		this.si_docs = this.get_doc_from_localstorage();
-		if (!this.si_docs.length) {
-			this.list_customers.find('.list-customers-table').html("");
-			return;
-		}
-
-		var html = "";
-		if(this.si_docs.length) {
-			this.si_docs.forEach(function (data, i) {
-				for (var key in data) {
-					html += frappe.render_template("pos_invoice_list", {
-						sr: i + 1,
-						name: key,
-						customer: data[key].customer,
-						paid_amount: format_currency(data[key].paid_amount, me.frm.doc.currency),
-						grand_total: format_currency(data[key].grand_total, me.frm.doc.currency),
-						data: me.get_doctype_status(data[key])
-					});
-				}
-			});
-		}
-		this.list_customers.find('.list-customers-table').html(html);
-
-		this.list_customers.on('click', '.customer-row', function () {
-			me.list_customers.hide();
-			me.numeric_keypad.show();
-			me.list_customers_btn.toggleClass("view_customer");
-			me.pos_bill.show();
-			me.list_customers_btn.show();
-			me.frm.doc.offline_pos_name = $(this).parents().attr('invoice-name');
-			me.edit_record();
-		})
-
-		//actions
-		$(this.wrapper).find('.list-select-all').click(function () {
-			me.list_customers.find('.list-delete').prop("checked", $(this).is(":checked"))
-			me.removed_items = [];
-			if ($(this).is(":checked")) {
-				$.each(me.si_docs, function (index, data) {
-					for (key in data) {
-						me.removed_items.push(key)
-					}
-				});
-			}
-
-			me.toggle_delete_button();
-		});
-
-		$(this.wrapper).find('.list-delete').click(function () {
-			me.frm.doc.offline_pos_name = $(this).parent().parent().attr('invoice-name');
-			if ($(this).is(":checked")) {
-				me.removed_items.push(me.frm.doc.offline_pos_name);
-			} else {
-				me.removed_items.pop(me.frm.doc.offline_pos_name)
-			}
-
-			me.toggle_delete_button();
-		});
-	},
-
-	bind_delete_event: function() {
-		var me = this;
-
-		$(this.page.wrapper).on('click', '.btn-danger', function(){
-			frappe.confirm(__("Delete permanently?"), function () {
-				me.delete_records();
-				me.list_customers.find('.list-customers-table').html("");
-				me.render_list_customers();
-			})
-		})
-	},
-
-	set_focus: function () {
-		if (this.default_customer || this.frm.doc.customer) {
-			this.set_customer_value_in_party_field();
-			this.search_item.$input.focus();
-		} else {
-			this.party_field.$input.focus();
-		}
-	},
-
-	make_customer: function () {
-		var me = this;
-
-		if(!this.party_field) {
-			if(this.page.wrapper.find('.pos-bill-toolbar').length === 0) {
-				$(frappe.render_template('customer_toolbar', {
-					allow_delete: this.pos_profile_data["allow_delete"]
-				})).insertAfter(this.page.$title_area.hide());
-			}
-
-			this.party_field = frappe.ui.form.make_control({
-				df: {
-					"fieldtype": "Data",
-					"options": this.party,
-					"label": this.party,
-					"fieldname": this.party.toLowerCase(),
-					"placeholder": __("Select or add new customer")
-				},
-				parent: this.page.wrapper.find(".party-area"),
-				only_input: true,
-			});
-
-			this.party_field.make_input();
-			setTimeout(this.set_focus.bind(this), 500);
-			me.toggle_delete_button();
-		}
-
-		this.party_field.awesomeplete =
-			new Awesomplete(this.party_field.$input.get(0), {
-				minChars: 0,
-				maxItems: 99,
-				autoFirst: true,
-				list: [],
-				filter: function (item, input) {
-					if (item.value.includes('is_action')) {
-						return true;
-					}
-
-					input = input.toLowerCase();
-					item = this.get_item(item.value);
-					result = item ? item.searchtext.includes(input) : '';
-					if(!result) {
-						me.prepare_customer_mapper(input);
-					} else {
-						return result;
-					}
-				},
-				item: function (item, input) {
-					var d = this.get_item(item.value);
-					var html = "<span>" + __(d.label || d.value) + "</span>";
-					if(d.customer_name) {
-						html += '<br><span class="text-muted ellipsis">' + __(d.customer_name) + '</span>';
-					}
-
-					return $('<li></li>')
-						.data('item.autocomplete', d)
-						.html('<a><p>' + html + '</p></a>')
-						.get(0);
-				}
-			});
-
-		this.prepare_customer_mapper()
-		this.autocomplete_customers();
-
-		this.party_field.$input
-			.on('input', function (e) {
-				if(me.customers_mapper.length <= 1) {
-					me.prepare_customer_mapper(e.target.value);
-				}
-				me.party_field.awesomeplete.list = me.customers_mapper;
-			})
-			.on('awesomplete-select', function (e) {
-				var customer = me.party_field.awesomeplete
-					.get_item(e.originalEvent.text.value);
-				if (!customer) return;
-				// create customer link
-				if (customer.action) {
-					customer.action.apply(me);
-					return;
-				}
-				me.toggle_list_customer(false);
-				me.toggle_edit_button(true);
-				me.update_customer_data(customer);
-				me.refresh();
-				me.set_focus();
-				me.list_customers_btn.removeClass("view_customer");
-			})
-			.on('focus', function (e) {
-				$(e.target).val('').trigger('input');
-				me.toggle_edit_button(false);
-
-				if(me.frm.doc.items.length) {
-					me.toggle_list_customer(false)
-					me.toggle_item_cart(true)
-				} else {
-					me.toggle_list_customer(true)
-					me.toggle_item_cart(false)
-				}
-			})
-			.on("awesomplete-selectcomplete", function (e) {
-				var item = me.party_field.awesomeplete
-					.get_item(e.originalEvent.text.value);
-				// clear text input if item is action
-				if (item.action) {
-					$(this).val("");
-				}
-				me.make_item_list(item.customer_name);
-			});
-	},
-
-	prepare_customer_mapper: function(key) {
-		var me = this;
-		var customer_data = '';
-
-		if (key) {
-			key = key.toLowerCase().trim();
-			var re = new RegExp('%', 'g');
-			var reg = new RegExp(key.replace(re, '\\w*\\s*[a-zA-Z0-9]*'));
-
-			customer_data =  $.grep(this.customers, function(data) {
-				contact = me.contacts[data.name];
-				if(reg.test(data.name.toLowerCase())
-					|| reg.test(data.customer_name.toLowerCase())
-					|| (contact && reg.test(contact["phone"]))
-					|| (contact && reg.test(contact["mobile_no"]))
-					|| (data.customer_group && reg.test(data.customer_group.toLowerCase()))){
-						return data;
-				}
-			})
-		} else {
-			customer_data = this.customers;
-		}
-
-		this.customers_mapper = [];
-
-		customer_data.forEach(function (c, index) {
-			if(index < 30) {
-				contact = me.contacts[c.name];
-				if(contact && !c['phone']) {
-					c["phone"] = contact["phone"];
-					c["email_id"] = contact["email_id"];
-					c["mobile_no"] = contact["mobile_no"];
-				}
-
-				me.customers_mapper.push({
-					label: c.name,
-					value: c.name,
-					customer_name: c.customer_name,
-					customer_group: c.customer_group,
-					territory: c.territory,
-					phone: contact ? contact["phone"] : '',
-					mobile_no: contact ? contact["mobile_no"] : '',
-					email_id: contact ? contact["email_id"] : '',
-					searchtext: ['customer_name', 'customer_group', 'name', 'value',
-						'label', 'email_id', 'phone', 'mobile_no']
-						.map(key => c[key]).join(' ')
-						.toLowerCase()
-				});
-			} else {
-				return;
-			}
-		});
-
-		this.customers_mapper.push({
-			label: "<span class='text-primary link-option'>"
-			+ "<i class='fa fa-plus' style='margin-right: 5px;'></i> "
-			+ __("Create a new Customer")
-			+ "</span>",
-			value: 'is_action',
-			action: me.add_customer
-		});
-	},
-
-	autocomplete_customers: function() {
-		this.party_field.awesomeplete.list = this.customers_mapper;
-	},
-
-	toggle_edit_button: function(flag) {
-		this.page.wrapper.find('.edit-customer-btn').toggle(flag);
-	},
-
-	toggle_list_customer: function(flag) {
-		this.list_customers.toggle(flag);
-	},
-
-	toggle_item_cart: function(flag) {
-		this.wrapper.find('.pos-bill-wrapper').toggle(flag);
-	},
-
-	add_customer: function() {
-		this.frm.doc.customer = "";
-		this.update_customer(true);
-		this.numeric_keypad.show();
-	},
-
-	update_customer: function (new_customer) {
-		var me = this;
-
-		this.customer_doc = new frappe.ui.Dialog({
-			'title': 'Customer',
-			fields: [
-				{
-					"label": __("Full Name"),
-					"fieldname": "full_name",
-					"fieldtype": "Data",
-					"reqd": 1
-				},
-				{
-					"fieldtype": "Section Break"
-				},
-				{
-					"label": __("Email Id"),
-					"fieldname": "email_id",
-					"fieldtype": "Data"
-				},
-				{
-					"fieldtype": "Column Break"
-				},
-				{
-					"label": __("Contact Number"),
-					"fieldname": "phone",
-					"fieldtype": "Data"
-				},
-				{
-					"fieldtype": "Section Break"
-				},
-				{
-					"label": __("Address Name"),
-					"read_only": 1,
-					"fieldname": "name",
-					"fieldtype": "Data"
-				},
-				{
-					"label": __("Address Line 1"),
-					"fieldname": "address_line1",
-					"fieldtype": "Data"
-				},
-				{
-					"label": __("Address Line 2"),
-					"fieldname": "address_line2",
-					"fieldtype": "Data"
-				},
-				{
-					"fieldtype": "Column Break"
-				},
-				{
-					"label": __("City"),
-					"fieldname": "city",
-					"fieldtype": "Data"
-				},
-				{
-					"label": __("State"),
-					"fieldname": "state",
-					"fieldtype": "Data"
-				},
-				{
-					"label": __("ZIP Code"),
-					"fieldname": "pincode",
-					"fieldtype": "Data"
-				},
-				{
-					"label": __("Customer POS Id"),
-					"fieldname": "customer_pos_id",
-					"fieldtype": "Data",
-					"hidden": 1
-				}
-			]
-		})
-		this.customer_doc.show()
-		this.render_address_data()
-
-		this.customer_doc.set_primary_action(__("Save"), function () {
-			me.make_offline_customer(new_customer);
-			me.pos_bill.show();
-			me.list_customers.hide();
-		});
-	},
-
-	render_address_data: function() {
-		var me = this;
-		this.address_data = this.address[this.frm.doc.customer] || {};
-		if(!this.address_data.email_id || !this.address_data.phone) {
-			this.address_data = this.contacts[this.frm.doc.customer];
-		}
-
-		this.customer_doc.set_values(this.address_data)
-		if(!this.customer_doc.fields_dict.full_name.$input.val()) {
-			this.customer_doc.set_value("full_name", this.frm.doc.customer)
-		}
-
-		if(!this.customer_doc.fields_dict.customer_pos_id.value) {
-			this.customer_doc.set_value("customer_pos_id", frappe.datetime.now_datetime())
-		}
-	},
-
-	get_address_from_localstorage: function() {
-		this.address_details = this.get_customers_details()
-		return this.address_details[this.frm.doc.customer]
-	},
-
-	make_offline_customer: function(new_customer) {
-		this.frm.doc.customer = this.frm.doc.customer || this.customer_doc.get_values().full_name;
-		this.frm.doc.customer_pos_id = this.customer_doc.fields_dict.customer_pos_id.value;
-		this.customer_details = this.get_customers_details();
-		this.customer_details[this.frm.doc.customer] = this.get_prompt_details();
-		this.party_field.$input.val(this.frm.doc.customer);
-		this.update_address_and_customer_list(new_customer)
-		this.autocomplete_customers();
-		this.update_customer_in_localstorage()
-		this.update_customer_in_localstorage()
-		this.customer_doc.hide()
-	},
-
-	update_address_and_customer_list: function(new_customer) {
-		var me = this;
-		if(new_customer) {
-			this.customers_mapper.push({
-				label: this.frm.doc.customer,
-				value: this.frm.doc.customer,
-				customer_group: "",
-				territory: ""
-			});
-		}
-
-		this.address[this.frm.doc.customer] = JSON.parse(this.get_prompt_details())
-	},
-
-	get_prompt_details: function() {
-		this.prompt_details = this.customer_doc.get_values();
-		this.prompt_details['country'] = this.pos_profile_data.country;
-		this.prompt_details['territory'] = this.pos_profile_data["territory"];
-		this.prompt_details['customer_group'] = this.pos_profile_data["customer_group"];
-		this.prompt_details['customer_pos_id'] = this.customer_doc.fields_dict.customer_pos_id.value;
-		return JSON.stringify(this.prompt_details)
-	},
-
-	update_customer_data: function (doc) {
-		var me = this;
-		this.frm.doc.customer = doc.label || doc.name;
-		this.frm.doc.customer_name = doc.customer_name;
-		this.frm.doc.customer_group = doc.customer_group;
-		this.frm.doc.territory = doc.territory;
-		this.pos_bill.show();
-		this.numeric_keypad.show();
-	},
-
-	make_item_list: function (customer) {
-		var me = this;
-		if (!this.price_list) {
-			frappe.msgprint(__("Price List not found or disabled"));
-			return;
-		}
-
-		me.item_timeout = null;
-
-		var $wrap = me.wrapper.find(".item-list");
-		me.wrapper.find(".item-list").empty();
-
-		if (this.items.length > 0) {
-			$.each(this.items, function(index, obj) {
-				let customer_price_list = me.customer_wise_price_list[customer];
-				let item_price
-				if (customer && customer_price_list && customer_price_list[obj.name]) {
-					item_price = format_currency(customer_price_list[obj.name], me.frm.doc.currency);
-				} else {
-					item_price = format_currency(me.price_list_data[obj.name], me.frm.doc.currency);
-				}
-				if(index < me.page_len) {
-					$(frappe.render_template("pos_item", {
-						item_code: obj.name,
-						item_price: item_price,
-						item_name: obj.name === obj.item_name ? "" : obj.item_name,
-						item_image: obj.image,
-						item_stock: __('Stock Qty') + ": " + me.get_actual_qty(obj),
-						item_uom: obj.stock_uom,
-						color: frappe.get_palette(obj.item_name),
-						abbr: frappe.get_abbr(obj.item_name)
-					})).tooltip().appendTo($wrap);
-				}
-			});
-
-			$wrap.append(`
-				<div class="image-view-item btn-more text-muted text-center">
-					<div class="image-view-body">
-						<i class="mega-octicon octicon-package"></i>
-						<div>Load more items</div>
-					</div>
-				</div>
-			`);
-
-			me.toggle_more_btn();
-		} else {
-			$("<p class='text-muted small' style='padding-left: 10px'>"
-				+__("Not items found")+"</p>").appendTo($wrap)
-		}
-
-		if (this.items.length == 1
-			&& this.search_item.$input.val()) {
-			this.search_item.$input.val("");
-			this.add_to_cart();
-		}
-	},
-
-	get_items: function (item_code) {
-		// To search item as per the key enter
-
-		var me = this;
-		this.item_serial_no = {};
-		this.item_batch_no = {};
-
-		if (item_code) {
-			return $.grep(this.item_data, function (item) {
-				if (item.item_code == item_code) {
-					return true
-				}
-			})
-		}
-
-		this.items_list = this.apply_category();
-
-		key = this.search_item.$input.val().toLowerCase().replace(/[&\/\\#,+()\[\]$~.'":*?<>{}]/g, '\\$&');
-		var re = new RegExp('%', 'g');
-		var reg = new RegExp(key.replace(re, '[\\w*\\s*[a-zA-Z0-9]*]*'))
-		search_status = true
-
-		if (key) {
-			return $.grep(this.items_list, function (item) {
-				if (search_status) {
-					if (me.batch_no_data[item.item_code] &&
-						in_list(me.batch_no_data[item.item_code], me.search_item.$input.val())) {
-						search_status = false;
-						return me.item_batch_no[item.item_code] = me.search_item.$input.val()
-					} else if (me.serial_no_data[item.item_code]
-						&& in_list(Object.keys(me.serial_no_data[item.item_code]), me.search_item.$input.val())) {
-						search_status = false;
-						me.item_serial_no[item.item_code] = [me.search_item.$input.val(), me.serial_no_data[item.item_code][me.search_item.$input.val()]]
-						return true
-					} else if (me.barcode_data[item.item_code] &&
-						in_list(me.barcode_data[item.item_code], me.search_item.$input.val())) {
-						search_status = false;
-						return true;
-					} else if (reg.test(item.item_code.toLowerCase()) || (item.description && reg.test(item.description.toLowerCase())) ||
-						reg.test(item.item_name.toLowerCase()) || reg.test(item.item_group.toLowerCase())) {
-						return true
-					}
-				}
-			})
-		} else {
-			return this.items_list;
-		}
-	},
-
-	apply_category: function() {
-		var me = this;
-		category = this.selected_item_group || "All Item Groups";
-		if(category == 'All Item Groups') {
-			return this.item_data
-		} else {
-			return this.item_data.filter(function(element, index, array){
-				return element.item_group == category;
-			});
-		}
-	},
-
-	bind_items_event: function() {
-		var me = this;
-		$(this.wrapper).on('click', '.pos-bill-item', function() {
-			$(me.wrapper).find('.pos-bill-item').removeClass('active');
-			$(this).addClass('active');
-			me.numeric_val = "";
-			me.numeric_id = ""
-			me.item_code = $(this).attr("data-item-code");
-			me.render_selected_item()
-			me.bind_qty_event()
-			me.update_rate()
-			$(me.wrapper).find(".selected-item").scrollTop(1000);
-		})
-	},
-
-	bind_qty_event: function () {
-		var me = this;
-
-		$(this.wrapper).on("change", ".pos-item-qty", function () {
-			var item_code = $(this).parents(".pos-selected-item-action").attr("data-item-code");
-			var qty = $(this).val();
-			me.update_qty(item_code, qty);
-			me.update_value();
-		})
-
-		$(this.wrapper).on("focusout", ".pos-item-qty", function () {
-			var item_code = $(this).parents(".pos-selected-item-action").attr("data-item-code");
-			var qty = $(this).val();
-			me.update_qty(item_code, qty, true);
-			me.update_value();
-		})
-
-		$(this.wrapper).find("[data-action='increase-qty']").on("click", function () {
-			var item_code = $(this).parents(".pos-bill-item").attr("data-item-code");
-			var qty = flt($(this).parents(".pos-bill-item").find('.pos-item-qty').val()) + 1;
-			me.update_qty(item_code, qty);
-		})
-
-		$(this.wrapper).find("[data-action='decrease-qty']").on("click", function () {
-			var item_code = $(this).parents(".pos-bill-item").attr("data-item-code");
-			var qty = flt($(this).parents(".pos-bill-item").find('.pos-item-qty').val()) - 1;
-			me.update_qty(item_code, qty);
-		})
-
-		$(this.wrapper).on("change", ".pos-item-disc", function () {
-			var item_code = $(this).parents(".pos-selected-item-action").attr("data-item-code");
-			var discount = $(this).val();
-			if(discount > 100){
-				discount = $(this).val('');
-				frappe.show_alert({
-					indicator: 'red',
-					message: __('Discount amount cannot be greater than 100%')
-				});
-				me.update_discount(item_code, discount);
-			}else{
-				me.update_discount(item_code, discount);
-				me.update_value();
-			}
-		})
-	},
-
-	bind_events: function() {
-		var me = this;
-		// if form is local then allow this function
-		// $(me.wrapper).find(".pos-item-wrapper").on("click", function () {
-		$(this.wrapper).on("click", ".pos-item-wrapper", function () {
-			me.item_code = '';
-			me.customer_validate();
-			if($(me.pos_bill).is(":hidden")) return;
-
-			if (me.frm.doc.docstatus == 0) {
-				me.items = me.get_items($(this).attr("data-item-code"))
-				me.add_to_cart();
-				me.clear_selected_row();
-			}
-		});
-
-		me.bind_delete_event()
-	},
-
-	update_qty: function (item_code, qty, remove_zero_qty_items) {
-		var me = this;
-		this.items = this.get_items(item_code);
-		this.validate_serial_no()
-		this.set_item_details(item_code, "qty", qty, remove_zero_qty_items);
-	},
-
-	update_discount: function(item_code, discount) {
-		var me = this;
-		this.items = this.get_items(item_code);
-		this.set_item_details(item_code, "discount_percentage", discount);
-	},
-
-	update_rate: function () {
-		var me = this;
-		$(this.wrapper).on("change", ".pos-item-price", function () {
-			var item_code = $(this).parents(".pos-selected-item-action").attr("data-item-code");
-			me.set_item_details(item_code, "rate", $(this).val());
-			me.update_value()
-		})
-	},
-
-	update_value: function() {
-		var me = this;
-		var fields = {qty: ".pos-item-qty", "discount_percentage": ".pos-item-disc",
-			"rate": ".pos-item-price", "amount": ".pos-amount"}
-		this.child_doc = this.get_child_item(this.item_code);
-
-		if(me.child_doc.length) {
-			$.each(fields, function(key, field) {
-				$(me.selected_row).find(field).val(me.child_doc[0][key])
-			})
-		} else {
-			this.clear_selected_row();
-		}
-	},
-
-	clear_selected_row: function() {
-		$(this.wrapper).find('.selected-item').empty();
-	},
-
-	render_selected_item: function() {
-		this.child_doc = this.get_child_item(this.item_code);
-		$(this.wrapper).find('.selected-item').empty();
-		if(this.child_doc.length) {
-			this.child_doc[0]["allow_user_to_edit_rate"] = this.pos_profile_data["allow_user_to_edit_rate"] ? true : false,
-			this.child_doc[0]["allow_user_to_edit_discount"] = this.pos_profile_data["allow_user_to_edit_discount"] ? true : false;
-			this.selected_row = $(frappe.render_template("pos_selected_item", this.child_doc[0]))
-			$(this.wrapper).find('.selected-item').html(this.selected_row)
-		}
-
-		$(this.selected_row).find('.form-control').click(function(){
-			$(this).select();
-		})
-	},
-
-	get_child_item: function(item_code) {
-		var me = this;
-		return $.map(me.frm.doc.items, function(doc){
-			if(doc.item_code == item_code) {
-				return doc
-			}
-		})
-	},
-
-	set_item_details: function (item_code, field, value, remove_zero_qty_items) {
-		var me = this;
-		if (value < 0) {
-			frappe.throw(__("Enter value must be positive"));
-		}
-
-		this.remove_item = []
-		$.each(this.frm.doc["items"] || [], function (i, d) {
-			if (d.item_code == item_code) {
-				if (d.serial_no && field == 'qty') {
-					me.validate_serial_no_qty(d, item_code, field, value)
-				}
-
-				d[field] = flt(value);
-				d.amount = flt(d.rate) * flt(d.qty);
-				if (d.qty == 0 && remove_zero_qty_items) {
-					me.remove_item.push(d.idx)
-				}
-
-				if(field=="discount_percentage" && value == 0) {
-					d.rate = d.price_list_rate;
-				}
-			}
-		});
-
-		if (field == 'qty') {
-			this.remove_zero_qty_items_from_cart();
-		}
-
-		this.update_paid_amount_status(false)
-	},
-
-	remove_zero_qty_items_from_cart: function () {
-		var me = this;
-		var idx = 0;
-		this.items = []
-		$.each(this.frm.doc["items"] || [], function (i, d) {
-			if (!in_list(me.remove_item, d.idx)) {
-				d.idx = idx;
-				me.items.push(d);
-				idx++;
-			}
-		});
-
-		this.frm.doc["items"] = this.items;
-	},
-
-	make_discount_field: function () {
-		var me = this;
-
-		this.wrapper.find('input.discount-percentage').on("change", function () {
-			me.frm.doc.additional_discount_percentage = flt($(this).val(), precision("additional_discount_percentage"));
-
-			if(me.frm.doc.additional_discount_percentage && me.frm.doc.discount_amount) {
-				// Reset discount amount
-				me.frm.doc.discount_amount = 0;
-			}
-
-			var total = me.frm.doc.grand_total
-
-			if (me.frm.doc.apply_discount_on == 'Net Total') {
-				total = me.frm.doc.net_total
-			}
-
-			me.frm.doc.discount_amount = flt(total * flt(me.frm.doc.additional_discount_percentage) / 100, precision("discount_amount"));
-			me.refresh();
-			me.wrapper.find('input.discount-amount').val(me.frm.doc.discount_amount)
-		});
-
-		this.wrapper.find('input.discount-amount').on("change", function () {
-			me.frm.doc.discount_amount = flt($(this).val(), precision("discount_amount"));
-			me.frm.doc.additional_discount_percentage = 0.0;
-			me.refresh();
-			me.wrapper.find('input.discount-percentage').val(0);
-		});
-	},
-
-	customer_validate: function () {
-		var me = this;
-		if (!this.frm.doc.customer || this.party_field.get_value() == "") {
-			frappe.throw(__("Please select customer"))
-		}
-	},
-
-	add_to_cart: function () {
-		var me = this;
-		var caught = false;
-		var no_of_items = me.wrapper.find(".pos-bill-item").length;
-
-		this.customer_validate();
-		this.mandatory_batch_no();
-		this.validate_serial_no();
-		this.validate_warehouse();
-
-		if (no_of_items != 0) {
-			$.each(this.frm.doc["items"] || [], function (i, d) {
-				if (d.item_code == me.items[0].item_code) {
-					caught = true;
-					d.qty += 1;
-					d.amount = flt(d.rate) * flt(d.qty);
-					if (me.item_serial_no[d.item_code]) {
-						d.serial_no += '\n' + me.item_serial_no[d.item_code][0]
-						d.warehouse = me.item_serial_no[d.item_code][1]
-					}
-
-					if (me.item_batch_no.length) {
-						d.batch_no = me.item_batch_no[d.item_code]
-					}
-				}
-			});
-		}
-
-		// if item not found then add new item
-		if (!caught)
-			this.add_new_item_to_grid();
-
-		this.update_paid_amount_status(false)
-		this.wrapper.find(".item-cart-items").scrollTop(1000);
-	},
-
-	add_new_item_to_grid: function () {
-		var me = this;
-		this.child = frappe.model.add_child(this.frm.doc, this.frm.doc.doctype + " Item", "items");
-		this.child.item_code = this.items[0].item_code;
-		this.child.item_name = this.items[0].item_name;
-		this.child.stock_uom = this.items[0].stock_uom;
-		this.child.uom = this.items[0].sales_uom || this.items[0].stock_uom;
-		this.child.conversion_factor = this.items[0].conversion_factor || 1;
-		this.child.brand = this.items[0].brand;
-		this.child.description = this.items[0].description || this.items[0].item_name;
-		this.child.discount_percentage = 0.0;
-		this.child.qty = 1;
-		this.child.item_group = this.items[0].item_group;
-		this.child.cost_center = this.pos_profile_data['cost_center'] || this.items[0].cost_center;
-		this.child.income_account = this.pos_profile_data['income_account'] || this.items[0].income_account;
-		this.child.warehouse = (this.item_serial_no[this.child.item_code]
-			? this.item_serial_no[this.child.item_code][1] : (this.pos_profile_data['warehouse'] || this.items[0].default_warehouse));
-
-		customer = this.frm.doc.customer;
-		let rate;
-
-		customer_price_list = this.customer_wise_price_list[customer]
-		if (customer_price_list && customer_price_list[this.child.item_code]){
-			rate = flt(this.customer_wise_price_list[customer][this.child.item_code] * this.child.conversion_factor, 9) / flt(this.frm.doc.conversion_rate, 9);
-		}
-		else{
-			rate = flt(this.price_list_data[this.child.item_code] * this.child.conversion_factor, 9) / flt(this.frm.doc.conversion_rate, 9);
-		}
-
-		this.child.price_list_rate = rate;
-		this.child.rate = rate;
-		this.child.actual_qty = me.get_actual_qty(this.items[0]);
-		this.child.amount = flt(this.child.qty) * flt(this.child.rate);
-		this.child.batch_no = this.item_batch_no[this.child.item_code];
-		this.child.serial_no = (this.item_serial_no[this.child.item_code]
-			? this.item_serial_no[this.child.item_code][0] : '');
-		this.child.item_tax_rate = JSON.stringify(this.tax_data[this.child.item_code]);
-	},
-
-	update_paid_amount_status: function (update_paid_amount) {
-		if (this.frm.doc.offline_pos_name) {
-			update_paid_amount = update_paid_amount ? false : true;
-		}
-
-		this.refresh(update_paid_amount);
-	},
-
-	refresh: function (update_paid_amount) {
-		var me = this;
-		this.refresh_fields(update_paid_amount);
-		this.set_primary_action();
-	},
-
-	refresh_fields: function (update_paid_amount) {
-		this.apply_pricing_rule();
-		this.discount_amount_applied = false;
-		this._calculate_taxes_and_totals();
-		this.calculate_discount_amount();
-		this.show_items_in_item_cart();
-		this.set_taxes();
-		this.calculate_outstanding_amount(update_paid_amount);
-		this.set_totals();
-		this.update_total_qty();
-	},
-
-	get_company_currency: function () {
-		return erpnext.get_currency(this.frm.doc.company);
-	},
-
-	show_items_in_item_cart: function () {
-		var me = this;
-		var $items = this.wrapper.find(".items").empty();
-		var $no_items_message = this.wrapper.find(".no-items-message");
-		$no_items_message.toggle(this.frm.doc.items.length === 0);
-
-		var $totals_area = this.wrapper.find('.totals-area');
-		$totals_area.toggle(this.frm.doc.items.length > 0);
-
-		$.each(this.frm.doc.items || [], function (i, d) {
-			$(frappe.render_template("pos_bill_item_new", {
-				item_code: d.item_code,
-				item_name: (d.item_name === d.item_code || !d.item_name) ? "" : ("<br>" + d.item_name),
-				qty: d.qty,
-				discount_percentage: d.discount_percentage || 0.0,
-				actual_qty: me.actual_qty_dict[d.item_code] || 0.0,
-				projected_qty: d.projected_qty,
-				rate: format_currency(d.rate, me.frm.doc.currency),
-				amount: format_currency(d.amount, me.frm.doc.currency),
-				selected_class: (me.item_code == d.item_code) ? "active" : ""
-			})).appendTo($items);
-		});
-
-		this.wrapper.find("input.pos-item-qty").on("focus", function () {
-			$(this).select();
-		});
-
-		this.wrapper.find("input.pos-item-disc").on("focus", function () {
-			$(this).select();
-		});
-
-		this.wrapper.find("input.pos-item-price").on("focus", function () {
-			$(this).select();
-		});
-	},
-
-	set_taxes: function () {
-		var me = this;
-		me.frm.doc.total_taxes_and_charges = 0.0
-
-		var taxes = this.frm.doc.taxes || [];
-		$(this.wrapper)
-			.find(".tax-area").toggleClass("hide", (taxes && taxes.length) ? false : true)
-			.find(".tax-table").empty();
-
-		$.each(taxes, function (i, d) {
-			if (d.tax_amount && cint(d.included_in_print_rate) == 0) {
-				$(frappe.render_template("pos_tax_row", {
-					description: d.description,
-					tax_amount: format_currency(flt(d.tax_amount_after_discount_amount),
-						me.frm.doc.currency)
-				})).appendTo(me.wrapper.find(".tax-table"));
-			}
-		});
-	},
-
-	set_totals: function () {
-		var me = this;
-		this.wrapper.find(".net-total").text(format_currency(me.frm.doc.total, me.frm.doc.currency));
-		this.wrapper.find(".grand-total").text(format_currency(me.frm.doc.grand_total, me.frm.doc.currency));
-		this.wrapper.find('input.discount-percentage').val(this.frm.doc.additional_discount_percentage);
-		this.wrapper.find('input.discount-amount').val(this.frm.doc.discount_amount);
-	},
-
-	update_total_qty: function() {
-		var me = this;
-		var qty_total = 0;
-			$.each(this.frm.doc["items"] || [], function (i, d) {
-				if (d.item_code) {
-					qty_total += d.qty;
-				}
-			});
-		this.frm.doc.qty_total = qty_total;
-		this.wrapper.find('.qty-total').text(this.frm.doc.qty_total);
-	},
-
-	set_primary_action: function () {
-		var me = this;
-		this.page.set_primary_action(__("New Cart"), function () {
-			me.make_new_cart()
-			me.make_menu_list()
-		}, "fa fa-plus")
-
-		if (this.frm.doc.docstatus == 1 || this.pos_profile_data["allow_print_before_pay"]) {
-			this.page.set_secondary_action(__("Print"), function () {
-				me.create_invoice();
-				var html = frappe.render(me.print_template_data, me.frm.doc)
-				me.print_document(html)
-			})
-		}
-
-		if (this.frm.doc.docstatus == 1) {
-			this.page.add_menu_item(__("Email"), function () {
-				me.email_prompt()
-			})
-		}
-	},
-
-	make_new_cart: function (){
-		this.item_code = '';
-		this.page.clear_secondary_action();
-		this.save_previous_entry();
-		this.create_new();
-		this.refresh();
-		this.toggle_input_field();
-		this.render_list_customers();
-		this.set_focus();
-	},
-
-	print_dialog: function () {
-		var me = this;
-
-		this.msgprint = frappe.msgprint(
-			`<a class="btn btn-primary print_doc"
-				style="margin-right: 5px;">${__('Print')}</a>
-			<a class="btn btn-default new_doc">${__('New')}</a>`);
-
-		this.msgprint.msg_area.find('.print_doc').on('click', function() {
-			var html = frappe.render(me.print_template_data, me.frm.doc);
-			me.print_document(html);
-		})
-
-		this.msgprint.msg_area.find('.new_doc').on('click', function() {
-			me.msgprint.hide();
-			me.make_new_cart();
-		})
-
-	},
-
-	print_document: function (html) {
-		var w = window.open();
-		w.document.write(html);
-		w.document.close();
-		setTimeout(function () {
-			w.print();
-			w.close();
-		}, 1000);
-	},
-
-	submit_invoice: function () {
-		var me = this;
-		this.change_status();
-		this.update_serial_no()
-		if (this.frm.doc.docstatus == 1) {
-			this.print_dialog()
-		}
-	},
-
-	update_serial_no: function() {
-		var me = this;
-
-		//Remove the sold serial no from the cache
-		$.each(this.frm.doc.items, function(index, data) {
-			var sn = data.serial_no.split('\n')
-			if(sn.length) {
-				var serial_no_list = me.serial_no_data[data.item_code]
-				if(serial_no_list) {
-					$.each(sn, function(i, serial_no) {
-						if(in_list(Object.keys(serial_no_list), serial_no)) {
-							delete serial_no_list[serial_no]
-						}
-					})
-					me.serial_no_data[data.item_code] = serial_no_list;
-				}
-			}
-		})
-	},
-
-	change_status: function () {
-		if (this.frm.doc.docstatus == 0) {
-			this.frm.doc.docstatus = 1;
-			this.update_invoice();
-			this.toggle_input_field();
-		}
-	},
-
-	toggle_input_field: function () {
-		var pointer_events = 'inherit'
-		var disabled = this.frm.doc.docstatus == 1 ? true: false;
-		$(this.wrapper).find('input').attr("disabled", disabled);
-		$(this.wrapper).find('select').attr("disabled", disabled);
-		$(this.wrapper).find('input').attr("disabled", disabled);
-		$(this.wrapper).find('select').attr("disabled", disabled);
-		$(this.wrapper).find('button').attr("disabled", disabled);
-		this.party_field.$input.attr('disabled', disabled);
-
-		if (this.frm.doc.docstatus == 1) {
-			pointer_events = 'none';
-		}
-
-		$(this.wrapper).find('.pos-bill').css('pointer-events', pointer_events);
-		$(this.wrapper).find('.pos-items-section').css('pointer-events', pointer_events);
-		this.set_primary_action();
-
-		$(this.wrapper).find('#pos-item-disc').prop('disabled',
-			this.pos_profile_data.allow_user_to_edit_discount ? false : true);
-
-		$(this.wrapper).find('#pos-item-price').prop('disabled',
-			this.pos_profile_data.allow_user_to_edit_rate ? false : true);
-	},
-
-	create_invoice: function () {
-		var me = this;
-		var existing_pos_list = [];
-		var invoice_data = {};
-		this.si_docs = this.get_doc_from_localstorage();
-
-		if(this.si_docs) {
-			this.si_docs.forEach((row) => {
-				existing_pos_list.push(Object.keys(row)[0]);
-			});
-		}
-
-		if (this.frm.doc.offline_pos_name
-			&& in_list(existing_pos_list, cstr(this.frm.doc.offline_pos_name))) {
-			this.update_invoice()
-		} else if(!this.frm.doc.offline_pos_name) {
-			this.frm.doc.offline_pos_name = frappe.datetime.now_datetime();
-			this.frm.doc.posting_date = frappe.datetime.get_today();
-			this.frm.doc.posting_time = frappe.datetime.now_time();
-			this.frm.doc.pos_total_qty = this.frm.doc.qty_total;
-			this.frm.doc.pos_profile = this.pos_profile_data['name'];
-			invoice_data[this.frm.doc.offline_pos_name] = this.frm.doc;
-			this.si_docs.push(invoice_data);
-			this.update_localstorage();
-			this.set_primary_action();
-		}
-		return invoice_data;
-	},
-
-	update_invoice: function () {
-		var me = this;
-		this.si_docs = this.get_doc_from_localstorage();
-		$.each(this.si_docs, function (index, data) {
-			for (var key in data) {
-				if (key == me.frm.doc.offline_pos_name) {
-					me.si_docs[index][key] = me.frm.doc;
-					me.update_localstorage();
-				}
-			}
-		});
-	},
-
-	update_localstorage: function () {
-		try {
-			localStorage.setItem('sales_invoice_doc', JSON.stringify(this.si_docs));
-		} catch (e) {
-			frappe.throw(__("LocalStorage is full , did not save"))
-		}
-	},
-
-	get_doc_from_localstorage: function () {
-		try {
-			return JSON.parse(localStorage.getItem('sales_invoice_doc')) || [];
-		} catch (e) {
-			return []
-		}
-	},
-
-	set_interval_for_si_sync: function () {
-		var me = this;
-		setInterval(function () {
-			me.freeze_screen = false;
-			me.sync_sales_invoice()
-		}, 180000)
-	},
-
-	sync_sales_invoice: function () {
-		var me = this;
-		this.si_docs = this.get_submitted_invoice() || [];
-		this.email_queue_list = this.get_email_queue() || {};
-		this.customers_list = this.get_customers_details() || {};
-
-		if (this.si_docs.length || this.email_queue_list || this.customers_list) {
-			frappe.call({
-				method: "erpnext.accounts.doctype.sales_invoice.pos.make_invoice",
-				freeze: true,
-				args: {
-					pos_profile: me.pos_profile_data,
-					doc_list: me.si_docs,
-					email_queue_list: me.email_queue_list,
-					customers_list: me.customers_list
-				},
-				callback: function (r) {
-					if (r.message) {
-						me.freeze = false;
-						me.customers = r.message.synced_customers_list;
-						me.address = r.message.synced_address;
-						me.contacts = r.message.synced_contacts;
-						me.removed_items = r.message.invoice;
-						me.removed_email = r.message.email_queue;
-						me.removed_customers = r.message.customers;
-						me.remove_doc_from_localstorage();
-						me.remove_email_queue_from_localstorage();
-						me.remove_customer_from_localstorage();
-						me.prepare_customer_mapper();
-						me.autocomplete_customers();
-						me.render_list_customers();
-					}
-				}
-			})
-		}
-	},
-
-	get_submitted_invoice: function () {
-		var invoices = [];
-		var index = 1;
-		var docs = this.get_doc_from_localstorage();
-		if (docs) {
-			invoices = $.map(docs, function (data) {
-				for (var key in data) {
-					if (data[key].docstatus == 1 && index < 50) {
-						index++
-						data[key].docstatus = 0;
-						return data
-					}
-				}
-			});
-		}
-
-		return invoices
-	},
-
-	remove_doc_from_localstorage: function () {
-		var me = this;
-		this.si_docs = this.get_doc_from_localstorage();
-		this.new_si_docs = [];
-		if (this.removed_items) {
-			$.each(this.si_docs, function (index, data) {
-				for (var key in data) {
-					if (!in_list(me.removed_items, key)) {
-						me.new_si_docs.push(data);
-					}
-				}
-			})
-			this.removed_items = [];
-			this.si_docs = this.new_si_docs;
-			this.update_localstorage();
-		}
-	},
-
-	remove_email_queue_from_localstorage: function() {
-		var me = this;
-		this.email_queue = this.get_email_queue()
-		if (this.removed_email) {
-			$.each(this.email_queue_list, function (index, data) {
-				if (in_list(me.removed_email, index)) {
-					delete me.email_queue[index]
-				}
-			})
-			this.update_email_queue();
-		}
-	},
-
-	remove_customer_from_localstorage: function() {
-		var me = this;
-		this.customer_details = this.get_customers_details()
-		if (this.removed_customers) {
-			$.each(this.customers_list, function (index, data) {
-				if (in_list(me.removed_customers, index)) {
-					delete me.customer_details[index]
-				}
-			})
-			this.update_customer_in_localstorage();
-		}
-	},
-
-	validate: function () {
-		var me = this;
-		this.customer_validate();
-		this.validate_zero_qty_items();
-		this.item_validate();
-		this.validate_mode_of_payments();
-	},
-
-	validate_zero_qty_items: function() {
-		this.remove_item = [];
-
-		this.frm.doc.items.forEach(d => {
-			if (d.qty == 0) {
-				this.remove_item.push(d.idx);
-			}
-		});
-
-		if(this.remove_item) {
-			this.remove_zero_qty_items_from_cart();
-		}
-	},
-
-	item_validate: function () {
-		if (this.frm.doc.items.length == 0) {
-			frappe.throw(__("Select items to save the invoice"))
-		}
-	},
-
-	validate_mode_of_payments: function () {
-		if (this.frm.doc.payments.length === 0) {
-			frappe.throw(__("Payment Mode is not configured. Please check, whether account has been set on Mode of Payments or on POS Profile."))
-		}
-	},
-
-	validate_serial_no: function () {
-		var me = this;
-		var item_code = ''
-		var serial_no = '';
-		for (var key in this.item_serial_no) {
-			item_code = key;
-			serial_no = me.item_serial_no[key][0];
-		}
-
-		if (this.items && this.items[0].has_serial_no && serial_no == "") {
-			this.refresh();
-			frappe.throw(__(repl("Error: Serial no is mandatory for item %(item)s", {
-				'item': this.items[0].item_code
-			})))
-		}
-
-		if (item_code && serial_no) {
-			$.each(this.frm.doc.items, function (index, data) {
-				if (data.item_code == item_code) {
-					if (in_list(data.serial_no.split('\n'), serial_no)) {
-						frappe.throw(__(repl("Serial no %(serial_no)s is already taken", {
-							'serial_no': serial_no
-						})))
-					}
-				}
-			})
-		}
-	},
-
-	validate_serial_no_qty: function (args, item_code, field, value) {
-		var me = this;
-		if (args.item_code == item_code && args.serial_no
-			&& field == 'qty' && cint(value) != value) {
-			args.qty = 0.0;
-			this.refresh();
-			frappe.throw(__("Serial no item cannot be a fraction"))
-		}
-
-		if (args.item_code == item_code && args.serial_no && args.serial_no.split('\n').length != cint(value)) {
-			args.qty = 0.0;
-			args.serial_no = ''
-			this.refresh();
-			frappe.throw(__(repl("Total nos of serial no is not equal to quantity for item %(item)s.", {
-				'item': item_code
-			})))
-		}
-	},
-
-	mandatory_batch_no: function () {
-		var me = this;
-		if (this.items[0].has_batch_no && !this.item_batch_no[this.items[0].item_code]) {
-			frappe.prompt([{
-				'fieldname': 'batch',
-				'fieldtype': 'Select',
-				'label': __('Batch No'),
-				'reqd': 1,
-				'options': this.batch_no_data[this.items[0].item_code]
-			}],
-			function(values){
-				me.item_batch_no[me.items[0].item_code] = values.batch;
-				const item = me.frm.doc.items.find(
-					({ item_code }) => item_code === me.items[0].item_code
-				);
-				if (item) {
-					item.batch_no = values.batch;
-				}
-			},
-			__('Select Batch No'))
-		}
-	},
-
-	apply_pricing_rule: function () {
-		var me = this;
-		$.each(this.frm.doc["items"], function (n, item) {
-			var pricing_rule = me.get_pricing_rule(item)
-			me.validate_pricing_rule(pricing_rule)
-			if (pricing_rule.length) {
-				item.pricing_rule = pricing_rule[0].name;
-				item.margin_type = pricing_rule[0].margin_type;
-				item.price_list_rate = pricing_rule[0].price || item.price_list_rate;
-				item.margin_rate_or_amount = pricing_rule[0].margin_rate_or_amount;
-				item.discount_percentage = pricing_rule[0].discount_percentage || 0.0;
-				me.apply_pricing_rule_on_item(item)
-			} else if (item.pricing_rule) {
-				item.price_list_rate = me.price_list_data[item.item_code]
-				item.margin_rate_or_amount = 0.0;
-				item.discount_percentage = 0.0;
-				item.pricing_rule = null;
-				me.apply_pricing_rule_on_item(item)
-			}
-
-			if(item.discount_percentage > 0) {
-				me.apply_pricing_rule_on_item(item)
-			}
-		})
-	},
-
-	get_pricing_rule: function (item) {
-		var me = this;
-		return $.grep(this.pricing_rules, function (data) {
-			if (item.qty >= data.min_qty && (item.qty <= (data.max_qty ? data.max_qty : item.qty))) {
-				if (me.validate_item_condition(data, item)) {
-					if (in_list(['Customer', 'Customer Group', 'Territory', 'Campaign'], data.applicable_for)) {
-						return me.validate_condition(data)
-					} else {
-						return true
-					}
-				}
-			}
-		})
-	},
-
-	validate_item_condition: function (data, item) {
-		var apply_on = frappe.model.scrub(data.apply_on);
-
-		return (data.apply_on == 'Item Group')
-			? this.validate_item_group(data.item_group, item.item_group) : (data[apply_on] == item[apply_on]);
-	},
-
-	validate_item_group: function (pr_item_group, cart_item_group) {
-		//pr_item_group = pricing rule's item group
-		//cart_item_group = cart item's item group
-		//this.item_groups has information about item group's lft and rgt
-		//for example: {'Foods': [12, 19]}
-
-		pr_item_group = this.item_groups[pr_item_group]
-		cart_item_group = this.item_groups[cart_item_group]
-
-		return (cart_item_group[0] >= pr_item_group[0] &&
-			cart_item_group[1] <= pr_item_group[1])
-	},
-
-	validate_condition: function (data) {
-		//This method check condition based on applicable for
-		var condition = this.get_mapper_for_pricing_rule(data)[data.applicable_for]
-		if (in_list(condition[1], condition[0])) {
-			return true
-		}
-	},
-
-	get_mapper_for_pricing_rule: function (data) {
-		return {
-			'Customer': [data.customer, [this.frm.doc.customer]],
-			'Customer Group': [data.customer_group, [this.frm.doc.customer_group, 'All Customer Groups']],
-			'Territory': [data.territory, [this.frm.doc.territory, 'All Territories']],
-			'Campaign': [data.campaign, [this.frm.doc.campaign]],
-		}
-	},
-
-	validate_pricing_rule: function (pricing_rule) {
-		//This method validate duplicate pricing rule
-		var pricing_rule_name = '';
-		var priority = 0;
-		var pricing_rule_list = [];
-		var priority_list = []
-
-		if (pricing_rule.length > 1) {
-
-			$.each(pricing_rule, function (index, data) {
-				pricing_rule_name += data.name + ','
-				priority_list.push(data.priority)
-				if (priority <= data.priority) {
-					priority = data.priority
-					pricing_rule_list.push(data)
-				}
-			})
-
-			var count = 0
-			$.each(priority_list, function (index, value) {
-				if (value == priority) {
-					count++
-				}
-			})
-
-			if (priority == 0 || count > 1) {
-				frappe.throw(__(repl("Multiple Price Rules exists with same criteria, please resolve conflict by assigning priority. Price Rules: %(pricing_rule)s", {
-					'pricing_rule': pricing_rule_name
-				})))
-			}
-
-			return pricing_rule_list
-		}
-	},
-
-	validate_warehouse: function () {
-		if (this.items[0].is_stock_item && !this.items[0].default_warehouse && !this.pos_profile_data['warehouse']) {
-			frappe.throw(__("Default warehouse is required for selected item"))
-		}
-	},
-
-	get_actual_qty: function (item) {
-		this.actual_qty = 0.0;
-
-		var warehouse = this.pos_profile_data['warehouse'] || item.default_warehouse;
-		if (warehouse && this.bin_data[item.item_code]) {
-			this.actual_qty = this.bin_data[item.item_code][warehouse] || 0;
-			this.actual_qty_dict[item.item_code] = this.actual_qty
-		}
-
-		return this.actual_qty
-	},
-
-	update_customer_in_localstorage: function() {
-		var me = this;
-		try {
-			localStorage.setItem('customer_details', JSON.stringify(this.customer_details));
-		} catch (e) {
-			frappe.throw(__("LocalStorage is full , did not save"))
-		}
-	}
-})
\ No newline at end of file
diff --git a/erpnext/accounts/page/pos/pos.json b/erpnext/accounts/page/pos/pos.json
deleted file mode 100644
index abd918a..0000000
--- a/erpnext/accounts/page/pos/pos.json
+++ /dev/null
@@ -1,28 +0,0 @@
-{
- "content": null, 
- "creation": "2014-08-08 02:45:55.931022", 
- "docstatus": 0, 
- "doctype": "Page", 
- "icon": "fa fa-th", 
- "modified": "2014-08-08 05:59:33.045012", 
- "modified_by": "Administrator", 
- "module": "Accounts", 
- "name": "pos", 
- "owner": "Administrator", 
- "page_name": "pos", 
- "roles": [
-  {
-   "role": "Sales User"
-  }, 
-  {
-   "role": "Purchase User"
-  }, 
-  {
-   "role": "Accounts User"
-  }
- ], 
- "script": null, 
- "standard": "Yes", 
- "style": null, 
- "title": "POS"
-}
\ No newline at end of file
diff --git a/erpnext/accounts/page/pos/test_pos.js b/erpnext/accounts/page/pos/test_pos.js
deleted file mode 100644
index e5524a2..0000000
--- a/erpnext/accounts/page/pos/test_pos.js
+++ /dev/null
@@ -1,52 +0,0 @@
-QUnit.test("test:Sales Invoice", function(assert) {
-	assert.expect(3);
-	let done = assert.async();
-
-	frappe.run_serially([
-		() => {
-			return frappe.tests.make("POS Profile", [
-				{naming_series: "SINV"},
-				{pos_profile_name: "_Test POS Profile"},
-				{country: "India"},
-				{currency: "INR"},
-				{write_off_account: "Write Off - FT"},
-				{write_off_cost_center: "Main - FT"},
-				{payments: [
-					[
-						{"default": 1},
-						{"mode_of_payment": "Cash"}
-					]]
-				}
-			]);
-		},
-		() => cur_frm.save(),
-		() => frappe.timeout(2),
-		() => {
-			assert.equal(cur_frm.doc.payments[0].default, 1, "Default mode of payment tested");
-		},
-		() => frappe.timeout(1),
-		() => {
-			return frappe.tests.make("Sales Invoice", [
-				{customer: "Test Customer 2"},
-				{is_pos: 1},
-				{posting_date: frappe.datetime.get_today()},
-				{due_date: frappe.datetime.get_today()},
-				{items: [
-					[
-						{"item_code": "Test Product 1"},
-						{"qty": 5},
-						{"warehouse":'Stores - FT'}
-					]]
-				}
-			]);
-		},
-		() => frappe.timeout(2),
-		() => cur_frm.save(),
-		() => frappe.timeout(2),
-		() => {
-			assert.equal(cur_frm.doc.payments[0].default, 1, "Default mode of payment tested");
-			assert.equal(cur_frm.doc.payments[0].mode_of_payment, "Cash", "Default mode of payment tested");
-		},
-		() => done()
-	]);
-});
\ No newline at end of file
diff --git a/erpnext/accounts/party.py b/erpnext/accounts/party.py
index db91b66..28a6519 100644
--- a/erpnext/accounts/party.py
+++ b/erpnext/accounts/party.py
@@ -184,7 +184,7 @@
 
 
 def set_account_and_due_date(party, account, party_type, company, posting_date, bill_date, doctype):
-	if doctype not in ["Sales Invoice", "Purchase Invoice"]:
+	if doctype not in ["POS Invoice", "Sales Invoice", "Purchase Invoice"]:
 		# not an invoice
 		return {
 			party_type.lower(): party
@@ -388,7 +388,7 @@
 	from erpnext.accounts.doctype.tax_rule.tax_rule import get_tax_template, get_party_details
 	args = {
 		party_type.lower(): party,
-		"company":			company
+		"company": company
 	}
 
 	if tax_category:
diff --git a/erpnext/accounts/page/pos/__init__.py b/erpnext/accounts/print_format/dunning_letter/__init__.py
similarity index 100%
copy from erpnext/accounts/page/pos/__init__.py
copy to erpnext/accounts/print_format/dunning_letter/__init__.py
diff --git a/erpnext/accounts/print_format/dunning_letter/dunning_letter.json b/erpnext/accounts/print_format/dunning_letter/dunning_letter.json
new file mode 100644
index 0000000..a7eac70
--- /dev/null
+++ b/erpnext/accounts/print_format/dunning_letter/dunning_letter.json
@@ -0,0 +1,25 @@
+{
+ "align_labels_right": 0,
+ "creation": "2019-12-11 04:37:14.012805",
+ "css": ".print-format th {\n    background-color: transparent !important;\n    border-bottom: 1px solid !important;\n    border-top: none !important;\n}\n.print-format .ql-editor {\n    padding-left: 0px;\n    padding-right: 0px;\n}\n\n.print-format table {\n    margin-bottom: 0px;\n    }\n.print-format .table-data tr:last-child { \n    border-bottom: 1px solid !important;\n}\n\n.print-format .table-inner tr:last-child {\n    border-bottom:none !important;\n}\n.print-format .table-inner {\n    margin: 0px 0px;\n}\n\n.print-format .table-data ul li { \n    color:#787878 !important;\n}\n\n.no-top-border {\n    border-top:none !important;\n}\n\n.table-inner td {\n    padding-left: 0px !important;    \n    padding-top: 1px !important;\n    padding-bottom: 1px !important;\n    color:#787878 !important;\n}\n\n.total {\n    background-color: lightgrey !important;\n    padding-top: 4px !important;\n    padding-bottom: 4px !important;\n}\n",
+ "custom_format": 0,
+ "default_print_language": "en",
+ "disabled": 0,
+ "doc_type": "Dunning",
+ "docstatus": 0,
+ "doctype": "Print Format",
+ "font": "Arial",
+ "format_data": "[{\"fieldname\": \"print_heading_template\", \"fieldtype\": \"Custom HTML\", \"options\": \"<div></div>\"}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"fieldname\": \"_custom_html\", \"print_hide\": 0, \"label\": \"Custom HTML\", \"fieldtype\": \"HTML\", \"options\": \"<b>{{doc.customer_name}}</b> <br />\\n{{doc.address_display}}\"}, {\"fieldtype\": \"Column Break\"}, {\"fieldname\": \"_custom_html\", \"print_hide\": 0, \"label\": \"Custom HTML\", \"fieldtype\": \"HTML\", \"options\": \"<div style=\\\"text-align:left;\\\">\\n<div style=\\\"font-size:24px; text-transform:uppercase;\\\">{{_(doc.dunning_type)}}</div>\\n<div style=\\\"font-size:16px;padding-bottom:5px;\\\">{{ doc.name }}</div>\\n</div>\"}, {\"fieldname\": \"posting_date\", \"print_hide\": 0, \"label\": \"Date\"}, {\"fieldname\": \"sales_invoice\", \"print_hide\": 0, \"label\": \"Sales Invoice\"}, {\"fieldname\": \"due_date\", \"print_hide\": 0, \"label\": \"Due Date\"}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"fieldname\": \"body_text\", \"print_hide\": 0, \"label\": \"Body Text\"}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"fieldname\": \"_custom_html\", \"print_hide\": 0, \"label\": \"Custom HTML\", \"fieldtype\": \"HTML\", \"options\": \"<table class=\\\"table table-borderless table-data\\\">\\n   <tbody>\\n        <tr>\\n            <th>{{_(\\\"Description\\\")}}</th>\\n\\t        <th style=\\\"text-align: right;\\\">{{_(\\\"Amount\\\")}}</th>\\n        </tr>\\n        <tr>\\n            <td>\\n                {{_(\\\"Outstanding Amount\\\")}}\\n             </td>\\n            <td style=\\\"text-align: right;\\\">\\n                {{doc.get_formatted(\\\"outstanding_amount\\\")}}\\n            </td>\\n        </tr>\\n        {%if doc.rate_of_interest > 0%}\\n        <tr>\\n            <td>\\n                {{_(\\\"Interest \\\")}} {{doc.rate_of_interest}}% p.a. ({{doc.overdue_days}} {{_(\\\"days\\\")}})\\n             </td>\\n            <td style=\\\"text-align: right;\\\">\\n                {{doc.get_formatted(\\\"interest_amount\\\")}}\\n            </td>\\n        </tr>\\n        {% endif %}\\n        {%if doc.dunning_fee > 0%}\\n        <tr>\\n            <td>\\n                {{_(\\\"Dunning Fee\\\")}}\\n             </td>\\n            <td style=\\\"text-align: right;\\\">\\n                {{doc.get_formatted(\\\"dunning_fee\\\")}}\\n            </td>\\n        </tr>\\n        {% endif %}\\n    </tbody>\\n</table>\"}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"fieldtype\": \"Column Break\"}, {\"fieldname\": \"_custom_html\", \"print_hide\": 0, \"label\": \"Custom HTML\", \"fieldtype\": \"HTML\", \"options\": \"\\n<div class=\\\"row total\\\" style =\\\"margin-right: 0px;\\\">\\n\\t\\t<div class=\\\"col-xs-5\\\">\\n\\t\\t\\t<b>{{_(\\\"Grand Total\\\")}}</b></div>\\n\\t\\t<div class=\\\"col-xs-7 text-right\\\" style=\\\"padding-right: 4px;\\\">\\n\\t\\t\\t<b>{{doc.get_formatted(\\\"grand_total\\\")}}</b>\\n\\t\\t</div>\\n</div>\\n\\n\"}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"fieldname\": \"closing_text\", \"print_hide\": 0, \"label\": \"Closing Text\"}]",
+ "idx": 0,
+ "line_breaks": 0,
+ "modified": "2020-07-14 18:25:44.348207",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "Dunning Letter",
+ "owner": "Administrator",
+ "print_format_builder": 0,
+ "print_format_type": "Jinja",
+ "raw_printing": 0,
+ "show_section_headings": 0,
+ "standard": "Yes"
+}
\ No newline at end of file
diff --git a/erpnext/accounts/print_format/gst_pos_invoice/gst_pos_invoice.json b/erpnext/accounts/print_format/gst_pos_invoice/gst_pos_invoice.json
index 1c5a195..1aa1c02 100644
--- a/erpnext/accounts/print_format/gst_pos_invoice/gst_pos_invoice.json
+++ b/erpnext/accounts/print_format/gst_pos_invoice/gst_pos_invoice.json
@@ -7,10 +7,10 @@
  "docstatus": 0,
  "doctype": "Print Format",
  "font": "Default",
- "html": "<style>\n\t.print-format table, .print-format tr, \n\t.print-format td, .print-format div, .print-format p {\n\t\tfont-family: Monospace;\n\t\tline-height: 200%;\n\t\tvertical-align: middle;\n\t}\n\t@media screen {\n\t\t.print-format {\n\t\t\twidth: 4in;\n\t\t\tpadding: 0.25in;\n\t\t\tmin-height: 8in;\n\t\t}\n\t}\n</style>\n\n{% if letter_head %}\n    {{ letter_head }}\n{% endif %}\n<p class=\"text-center\">\n\t{{ doc.company }}<br>\n\t{% if doc.company_address_display %}\n\t\t{% set company_address = doc.company_address_display.replace(\"\\n\", \" \").replace(\"<br>\", \" \") %}\n\t\t{% if \"GSTIN\" not in company_address %}\n\t\t\t{{ company_address }}\n\t\t\t<b>{{ _(\"GSTIN\") }}:</b>{{ doc.company_gstin }}\n\t\t{% else %}\n\t\t\t{{ company_address.replace(\"GSTIN\", \"<br>GSTIN\") }}\n\t\t{% endif %}\n\t{% endif %}\n\t<br>\n\t{% if doc.docstatus == 0 %}\n\t\t<b>{{ doc.status + \" \"+ (doc.select_print_heading or _(\"Invoice\")) }}</b><br>\n\t{% else %}\n\t\t<b>{{ doc.select_print_heading or _(\"Invoice\") }}</b><br>\n\t{% endif %}\n</p>\n<p>\n\t<b>{{ _(\"Receipt No\") }}:</b> {{ doc.name }}<br>\n\t<b>{{ _(\"Date\") }}:</b> {{ doc.get_formatted(\"posting_date\") }}<br>\n\t{% if doc.grand_total > 50000 %}\n\t\t{% set customer_address = doc.address_display.replace(\"\\n\", \" \").replace(\"<br>\", \" \") %}\n\t\t<b>{{ _(\"Customer\") }}:</b><br>\n\t\t{{ doc.customer_name }}<br>\n\t\t{{ customer_address }}\n\t{% endif %}\n</p>\n\n<hr>\n<table class=\"table table-condensed cart no-border\">\n\t<thead>\n\t\t<tr>\n\t\t\t<th width=\"40%\">{{ _(\"Item\") }}</b></th>\n\t\t\t<th width=\"30%\" class=\"text-right\">{{ _(\"Qty\") }}</th>\n\t\t\t<th width=\"30%\" class=\"text-right\">{{ _(\"Amount\") }}</th>\n\t\t</tr>\n\t</thead>\n\t<tbody>\n\t\t{%- for item in doc.items -%}\n\t\t<tr>\n\t\t\t<td>\n\t\t\t\t{{ item.item_code }}\n\t\t\t\t{%- if item.item_name != item.item_code -%}\n\t\t\t\t\t<br>{{ item.item_name }}\n\t\t\t\t{%- endif -%}\n\t\t\t\t{%- if item.gst_hsn_code -%}\n\t\t\t\t\t<br><b>{{ _(\"HSN/SAC\") }}:</b> {{ item.gst_hsn_code }}\n\t\t\t\t{%- endif -%}\n\t\t\t\t{%- if item.serial_no -%}\n\t\t\t\t\t<br><b>{{ _(\"Serial No\") }}:</b> {{ item.serial_no }}\n\t\t\t\t{%- endif -%}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">{{ item.qty }}<br>@ {{ item.rate }}</td>\n\t\t\t<td class=\"text-right\">{{ item.get_formatted(\"amount\") }}</td>\n\t\t</tr>\n\t\t{%- endfor -%}\n\t</tbody>\n</table>\n<table class=\"table table-condensed no-border\">\n\t<tbody>\n\t\t<tr>\n\t\t\t{% if doc.flags.show_inclusive_tax_in_print %}\n\t\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t\t{{ _(\"Total Excl. Tax\") }}\n\t\t\t\t</td>\n\t\t\t\t<td class=\"text-right\">\n\t\t\t\t\t{{ doc.get_formatted(\"net_total\", doc) }}\n\t\t\t\t</td>\n\t\t\t{% else %}\n\t\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t\t{{ _(\"Total\") }}\n\t\t\t\t</td>\n\t\t\t\t<td class=\"text-right\">\n\t\t\t\t\t{{ doc.get_formatted(\"total\", doc) }}\n\t\t\t\t</td>\n\t\t\t{% endif %}\n\t\t</tr>\n\t\t{%- for row in doc.taxes -%}\n\t\t  {%- if (not row.included_in_print_rate or doc.flags.show_inclusive_tax_in_print) and row.tax_amount != 0 -%}\n\t\t\t<tr>\n\t\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t\t{{ row.description }}\n\t\t\t\t</td>\n\t\t\t\t<td class=\"text-right\">\n\t\t\t\t\t{{ row.get_formatted(\"tax_amount\", doc) }}\n\t\t\t\t</td>\n\t\t\t<tr>\n\t\t  {%- endif -%}\n\t\t{%- endfor -%}\n\t\t{%- if doc.discount_amount -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t{{ _(\"Discount\") }}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"discount_amount\") }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- endif -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t<b>{{ _(\"Grand Total\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"grand_total\") }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- if doc.rounded_total -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t<b>{{ _(\"Rounded Total\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"rounded_total\") }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- endif -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t<b>{{ _(\"Paid Amount\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"paid_amount\") }}\n\t\t\t</td>\n\t\t</tr>\n\t{%- if doc.change_amount -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t<b>{{ _(\"Change Amount\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"change_amount\") }}\n\t\t\t</td>\n\t\t</tr>\n\t{%- endif -%}\n\t</tbody>\n</table>\n<p>{{ doc.terms or \"\" }}</p>\n<p class=\"text-center\">{{ _(\"Thank you, please visit again.\") }}</p>",
+ "html": "<style>\n\t.print-format table, .print-format tr, \n\t.print-format td, .print-format div, .print-format p {\n\t\tfont-family: Tahoma, sans-serif;\n\t\tline-height: 150%;\n\t\tvertical-align: middle;\n\t}\n\t@media screen {\n\t\t.print-format {\n\t\t\twidth: 4in;\n\t\t\tpadding: 0.25in;\n\t\t\tmin-height: 8in;\n\t\t}\n\t}\n</style>\n\n{% if letter_head %}\n    {{ letter_head }}\n{% endif %}\n<p class=\"text-center\">\n\t{{ doc.company }}<br>\n\t{% if doc.company_address_display %}\n\t\t{% set company_address = doc.company_address_display.replace(\"\\n\", \" \").replace(\"<br>\", \" \") %}\n\t\t{% if \"GSTIN\" not in company_address %}\n\t\t\t{{ company_address }}\n\t\t\t<b>{{ _(\"GSTIN\") }}:</b>{{ doc.company_gstin }}\n\t\t{% else %}\n\t\t\t{{ company_address.replace(\"GSTIN\", \"<br>GSTIN\") }}\n\t\t{% endif %}\n\t{% endif %}\n\t<br>\n\t{% if doc.docstatus == 0 %}\n\t\t<b>{{ doc.status + \" \"+ (doc.select_print_heading or _(\"Invoice\")) }}</b><br>\n\t{% else %}\n\t\t<b>{{ doc.select_print_heading or _(\"Invoice\") }}</b><br>\n\t{% endif %}\n</p>\n<p>\n\t<b>{{ _(\"Receipt No\") }}:</b> {{ doc.name }}<br>\n\t<b>{{ _(\"Date\") }}:</b> {{ doc.get_formatted(\"posting_date\") }}<br>\n\t{% if doc.grand_total > 50000 %}\n\t\t{% set customer_address = doc.address_display.replace(\"\\n\", \" \").replace(\"<br>\", \" \") %}\n\t\t<b>{{ _(\"Customer\") }}:</b><br>\n\t\t{{ doc.customer_name }}<br>\n\t\t{{ customer_address }}\n\t{% endif %}\n</p>\n\n<hr>\n<table class=\"table table-condensed cart no-border\">\n\t<thead>\n\t\t<tr>\n\t\t\t<th width=\"50%\">{{ _(\"Item\") }}</b></th>\n\t\t\t<th width=\"25%\" class=\"text-right\">{{ _(\"Qty\") }}</th>\n\t\t\t<th width=\"25%\" class=\"text-right\">{{ _(\"Amount\") }}</th>\n\t\t</tr>\n\t</thead>\n\t<tbody>\n\t\t{%- for item in doc.items -%}\n\t\t<tr>\n\t\t\t<td>\n\t\t\t\t{{ item.item_code }}\n\t\t\t\t{%- if item.item_name != item.item_code -%}\n\t\t\t\t\t<br>{{ item.item_name }}\n\t\t\t\t{%- endif -%}\n\t\t\t\t{%- if item.gst_hsn_code -%}\n\t\t\t\t\t<br><b>{{ _(\"HSN/SAC\") }}:</b> {{ item.gst_hsn_code }}\n\t\t\t\t{%- endif -%}\n\t\t\t\t{%- if item.serial_no -%}\n\t\t\t\t\t<br><b>{{ _(\"Serial No\") }}:</b> {{ item.serial_no }}\n\t\t\t\t{%- endif -%}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">{{ item.qty }}<br>@ {{ item.rate }}</td>\n\t\t\t<td class=\"text-right\">{{ item.get_formatted(\"amount\") }}</td>\n\t\t</tr>\n\t\t{%- endfor -%}\n\t</tbody>\n</table>\n<table class=\"table table-condensed no-border\">\n\t<tbody>\n\t\t<tr>\n\t\t\t{% if doc.flags.show_inclusive_tax_in_print %}\n\t\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t\t{{ _(\"Total Excl. Tax\") }}\n\t\t\t\t</td>\n\t\t\t\t<td class=\"text-right\">\n\t\t\t\t\t{{ doc.get_formatted(\"net_total\", doc) }}\n\t\t\t\t</td>\n\t\t\t{% else %}\n\t\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t\t{{ _(\"Total\") }}\n\t\t\t\t</td>\n\t\t\t\t<td class=\"text-right\">\n\t\t\t\t\t{{ doc.get_formatted(\"total\", doc) }}\n\t\t\t\t</td>\n\t\t\t{% endif %}\n\t\t</tr>\n\t\t{%- for row in doc.taxes -%}\n\t\t  {%- if (not row.included_in_print_rate or doc.flags.show_inclusive_tax_in_print) and row.tax_amount != 0 -%}\n\t\t\t<tr>\n\t\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t\t{{ row.description }}\n\t\t\t\t</td>\n\t\t\t\t<td class=\"text-right\">\n\t\t\t\t\t{{ row.get_formatted(\"tax_amount\", doc) }}\n\t\t\t\t</td>\n\t\t\t<tr>\n\t\t  {%- endif -%}\n\t\t{%- endfor -%}\n\t\t{%- if doc.discount_amount -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t{{ _(\"Discount\") }}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"discount_amount\") }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- endif -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t<b>{{ _(\"Grand Total\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"grand_total\") }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- if doc.rounded_total -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t<b>{{ _(\"Rounded Total\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"rounded_total\") }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- endif -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t<b>{{ _(\"Paid Amount\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"paid_amount\") }}\n\t\t\t</td>\n\t\t</tr>\n\t{%- if doc.change_amount -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t<b>{{ _(\"Change Amount\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"change_amount\") }}\n\t\t\t</td>\n\t\t</tr>\n\t{%- endif -%}\n\t</tbody>\n</table>\n<p>{{ doc.terms or \"\" }}</p>\n<p class=\"text-center\">{{ _(\"Thank you, please visit again.\") }}</p>",
  "idx": 0,
  "line_breaks": 0,
- "modified": "2019-12-09 17:39:23.356573",
+ "modified": "2020-04-29 16:39:12.936215",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "GST POS Invoice",
diff --git a/erpnext/accounts/print_format/pos_invoice/pos_invoice.json b/erpnext/accounts/print_format/pos_invoice/pos_invoice.json
index be69922..13a973d 100644
--- a/erpnext/accounts/print_format/pos_invoice/pos_invoice.json
+++ b/erpnext/accounts/print_format/pos_invoice/pos_invoice.json
@@ -6,10 +6,10 @@
  "doc_type": "Sales Invoice",
  "docstatus": 0,
  "doctype": "Print Format",
- "html": "<style>\n\t.print-format table, .print-format tr, \n\t.print-format td, .print-format div, .print-format p {\n\t\tfont-family: Monospace;\n\t\tline-height: 200%;\n\t\tvertical-align: middle;\n\t}\n\t@media screen {\n\t\t.print-format {\n\t\t\twidth: 4in;\n\t\t\tpadding: 0.25in;\n\t\t\tmin-height: 8in;\n\t\t}\n\t}\n</style>\n\n{% if letter_head %}\n    {{ letter_head }}\n{% endif %}\n\n<p class=\"text-center\">\n\t{{ doc.company }}<br>\n\t{{ doc.select_print_heading or _(\"Invoice\") }}<br>\n</p>\n<p>\n\t<b>{{ _(\"Receipt No\") }}:</b> {{ doc.name }}<br>\n\t<b>{{ _(\"Date\") }}:</b> {{ doc.get_formatted(\"posting_date\") }}<br>\n\t<b>{{ _(\"Customer\") }}:</b> {{ doc.customer_name }}\n</p>\n\n<hr>\n<table class=\"table table-condensed cart no-border\">\n\t<thead>\n\t\t<tr>\n\t\t\t<th width=\"50%\">{{ _(\"Item\") }}</b></th>\n\t\t\t<th width=\"25%\" class=\"text-right\">{{ _(\"Qty\") }}</th>\n\t\t\t<th width=\"25%\" class=\"text-right\">{{ _(\"Amount\") }}</th>\n\t\t</tr>\n\t</thead>\n\t<tbody>\n\t\t{%- for item in doc.items -%}\n\t\t<tr>\n\t\t\t<td>\n\t\t\t\t{{ item.item_code }}\n\t\t\t\t{%- if item.item_name != item.item_code -%}\n\t\t\t\t\t<br>{{ item.item_name }}{%- endif -%}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">{{ item.qty }}<br>@ {{ item.get_formatted(\"rate\") }}</td>\n\t\t\t<td class=\"text-right\">{{ item.get_formatted(\"amount\") }}</td>\n\t\t</tr>\n\t\t{%- endfor -%}\n\t</tbody>\n</table>\n<table class=\"table table-condensed no-border\">\n\t<tbody>\n\t\t<tr>\n\t\t\t{% if doc.flags.show_inclusive_tax_in_print %}\n\t\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t\t{{ _(\"Total Excl. Tax\") }}\n\t\t\t\t</td>\n\t\t\t\t<td class=\"text-right\">\n\t\t\t\t\t{{ doc.get_formatted(\"net_total\", doc) }}\n\t\t\t\t</td>\n\t\t\t{% else %}\n\t\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t\t{{ _(\"Total\") }}\n\t\t\t\t</td>\n\t\t\t\t<td class=\"text-right\">\n\t\t\t\t\t{{ doc.get_formatted(\"total\", doc) }}\n\t\t\t\t</td>\n\t\t\t{% endif %}\n\t\t</tr>\n\t\t{%- for row in doc.taxes -%}\n\t\t  {%- if not row.included_in_print_rate or doc.flags.show_inclusive_tax_in_print -%}\n\t\t\t<tr>\n\t\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t\t{{ row.description }}\n\t\t\t\t</td>\n\t\t\t\t<td class=\"text-right\">\n\t\t\t\t\t{{ row.get_formatted(\"tax_amount\", doc) }}\n\t\t\t\t</td>\n\t\t\t<tr>\n\t\t  {%- endif -%}\n\t\t{%- endfor -%}\n\n\t\t{%- if doc.discount_amount -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t{{ _(\"Discount\") }}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"discount_amount\") }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- endif -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t<b>{{ _(\"Grand Total\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"grand_total\") }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- if doc.rounded_total -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t<b>{{ _(\"Rounded Total\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"rounded_total\") }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- endif -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t<b>{{ _(\"Paid Amount\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"paid_amount\") }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- if doc.change_amount -%}\n\t\t\t<tr>\n\t\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t\t<b>{{ _(\"Change Amount\") }}</b>\n\t\t\t\t</td>\n\t\t\t\t<td class=\"text-right\">\n\t\t\t\t\t{{ doc.get_formatted(\"change_amount\") }}\n\t\t\t\t</td>\n\t\t\t</tr>\n\t\t{%- endif -%}\n\t</tbody>\n</table>\n<hr>\n<p>{{ doc.terms or \"\" }}</p>\n<p class=\"text-center\">{{ _(\"Thank you, please visit again.\") }}</p>",
+ "html": "<style>\n\t.print-format table, .print-format tr, \n\t.print-format td, .print-format div, .print-format p {\n\t\tfont-family: Tahoma, sans-serif;\n\t\tline-height: 150%;\n\t\tvertical-align: middle;\n\t}\n\t@media screen {\n\t\t.print-format {\n\t\t\twidth: 4in;\n\t\t\tpadding: 0.25in;\n\t\t\tmin-height: 8in;\n\t\t}\n\t}\n</style>\n\n{% if letter_head %}\n    {{ letter_head }}\n{% endif %}\n\n<p class=\"text-center\" style=\"margin-bottom: 1rem\">\n\t{{ doc.company }}<br>\n\t{{ doc.select_print_heading or _(\"Invoice\") }}<br>\n</p>\n<p>\n\t<b>{{ _(\"Receipt No\") }}:</b> {{ doc.name }}<br>\n\t<b>{{ _(\"Date\") }}:</b> {{ doc.get_formatted(\"posting_date\") }}<br>\n\t<b>{{ _(\"Customer\") }}:</b> {{ doc.customer_name }}\n</p>\n\n<hr>\n<table class=\"table table-condensed cart no-border\">\n\t<thead>\n\t\t<tr>\n\t\t\t<th width=\"50%\">{{ _(\"Item\") }}</b></th>\n\t\t\t<th width=\"25%\" class=\"text-right\">{{ _(\"Qty\") }}</th>\n\t\t\t<th width=\"25%\" class=\"text-right\">{{ _(\"Amount\") }}</th>\n\t\t</tr>\n\t</thead>\n\t<tbody>\n\t\t{%- for item in doc.items -%}\n\t\t<tr>\n\t\t\t<td>\n\t\t\t\t{{ item.item_code }}\n\t\t\t\t{%- if item.item_name != item.item_code -%}\n\t\t\t\t\t<br>{{ item.item_name }}{%- endif -%}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">{{ item.qty }}<br>@ {{ item.get_formatted(\"rate\") }}</td>\n\t\t\t<td class=\"text-right\">{{ item.get_formatted(\"amount\") }}</td>\n\t\t</tr>\n\t\t{%- endfor -%}\n\t</tbody>\n</table>\n<table class=\"table table-condensed no-border\">\n\t<tbody>\n\t\t<tr>\n\t\t\t{% if doc.flags.show_inclusive_tax_in_print %}\n\t\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t\t{{ _(\"Total Excl. Tax\") }}\n\t\t\t\t</td>\n\t\t\t\t<td class=\"text-right\">\n\t\t\t\t\t{{ doc.get_formatted(\"net_total\", doc) }}\n\t\t\t\t</td>\n\t\t\t{% else %}\n\t\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t\t{{ _(\"Total\") }}\n\t\t\t\t</td>\n\t\t\t\t<td class=\"text-right\">\n\t\t\t\t\t{{ doc.get_formatted(\"total\", doc) }}\n\t\t\t\t</td>\n\t\t\t{% endif %}\n\t\t</tr>\n\t\t{%- for row in doc.taxes -%}\n\t\t  {%- if not row.included_in_print_rate or doc.flags.show_inclusive_tax_in_print -%}\n\t\t\t<tr>\n\t\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t\t{{ row.description }}\n\t\t\t\t</td>\n\t\t\t\t<td class=\"text-right\">\n\t\t\t\t\t{{ row.get_formatted(\"tax_amount\", doc) }}\n\t\t\t\t</td>\n\t\t\t<tr>\n\t\t  {%- endif -%}\n\t\t{%- endfor -%}\n\n\t\t{%- if doc.discount_amount -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t{{ _(\"Discount\") }}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"discount_amount\") }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- endif -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t<b>{{ _(\"Grand Total\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"grand_total\") }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- if doc.rounded_total -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t<b>{{ _(\"Rounded Total\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"rounded_total\") }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- endif -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t<b>{{ _(\"Paid Amount\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"paid_amount\") }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- if doc.change_amount -%}\n\t\t\t<tr>\n\t\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t\t<b>{{ _(\"Change Amount\") }}</b>\n\t\t\t\t</td>\n\t\t\t\t<td class=\"text-right\">\n\t\t\t\t\t{{ doc.get_formatted(\"change_amount\") }}\n\t\t\t\t</td>\n\t\t\t</tr>\n\t\t{%- endif -%}\n\t</tbody>\n</table>\n<hr>\n<p>{{ doc.terms or \"\" }}</p>\n<p class=\"text-center\">{{ _(\"Thank you, please visit again.\") }}</p>",
  "idx": 1,
  "line_breaks": 0,
- "modified": "2019-12-09 17:40:53.183574",
+ "modified": "2020-04-29 16:35:07.043058",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "POS Invoice",
diff --git a/erpnext/accounts/report/accounts_payable/accounts_payable.js b/erpnext/accounts/report/accounts_payable/accounts_payable.js
index 2aa9618..6abd6e5 100644
--- a/erpnext/accounts/report/accounts_payable/accounts_payable.js
+++ b/erpnext/accounts/report/accounts_payable/accounts_payable.js
@@ -18,41 +18,6 @@
 			"default": frappe.datetime.get_today()
 		},
 		{
-			"fieldname":"ageing_based_on",
-			"label": __("Ageing Based On"),
-			"fieldtype": "Select",
-			"options": 'Posting Date\nDue Date\nSupplier Invoice Date',
-			"default": "Due Date"
-		},
-		{
-			"fieldname":"range1",
-			"label": __("Ageing Range 1"),
-			"fieldtype": "Int",
-			"default": "30",
-			"reqd": 1
-		},
-		{
-			"fieldname":"range2",
-			"label": __("Ageing Range 2"),
-			"fieldtype": "Int",
-			"default": "60",
-			"reqd": 1
-		},
-		{
-			"fieldname":"range3",
-			"label": __("Ageing Range 3"),
-			"fieldtype": "Int",
-			"default": "90",
-			"reqd": 1
-		},
-		{
-			"fieldname":"range4",
-			"label": __("Ageing Range 4"),
-			"fieldtype": "Int",
-			"default": "120",
-			"reqd": 1
-		},
-		{
 			"fieldname":"finance_book",
 			"label": __("Finance Book"),
 			"fieldtype": "Link",
@@ -89,6 +54,41 @@
 			}
 		},
 		{
+			"fieldname":"ageing_based_on",
+			"label": __("Ageing Based On"),
+			"fieldtype": "Select",
+			"options": 'Posting Date\nDue Date\nSupplier Invoice Date',
+			"default": "Due Date"
+		},
+		{
+			"fieldname":"range1",
+			"label": __("Ageing Range 1"),
+			"fieldtype": "Int",
+			"default": "30",
+			"reqd": 1
+		},
+		{
+			"fieldname":"range2",
+			"label": __("Ageing Range 2"),
+			"fieldtype": "Int",
+			"default": "60",
+			"reqd": 1
+		},
+		{
+			"fieldname":"range3",
+			"label": __("Ageing Range 3"),
+			"fieldtype": "Int",
+			"default": "90",
+			"reqd": 1
+		},
+		{
+			"fieldname":"range4",
+			"label": __("Ageing Range 4"),
+			"fieldtype": "Int",
+			"default": "120",
+			"reqd": 1
+		},
+		{
 			"fieldname":"payment_terms_template",
 			"label": __("Payment Terms Template"),
 			"fieldtype": "Link",
diff --git a/erpnext/accounts/report/accounts_receivable/accounts_receivable.js b/erpnext/accounts/report/accounts_receivable/accounts_receivable.js
index 8dc558a..c999eb9 100644
--- a/erpnext/accounts/report/accounts_receivable/accounts_receivable.js
+++ b/erpnext/accounts/report/accounts_receivable/accounts_receivable.js
@@ -18,41 +18,6 @@
 			"default": frappe.datetime.get_today()
 		},
 		{
-			"fieldname":"ageing_based_on",
-			"label": __("Ageing Based On"),
-			"fieldtype": "Select",
-			"options": 'Posting Date\nDue Date',
-			"default": "Due Date"
-		},
-		{
-			"fieldname":"range1",
-			"label": __("Ageing Range 1"),
-			"fieldtype": "Int",
-			"default": "30",
-			"reqd": 1
-		},
-		{
-			"fieldname":"range2",
-			"label": __("Ageing Range 2"),
-			"fieldtype": "Int",
-			"default": "60",
-			"reqd": 1
-		},
-		{
-			"fieldname":"range3",
-			"label": __("Ageing Range 3"),
-			"fieldtype": "Int",
-			"default": "90",
-			"reqd": 1
-		},
-		{
-			"fieldname":"range4",
-			"label": __("Ageing Range 4"),
-			"fieldtype": "Int",
-			"default": "120",
-			"reqd": 1
-		},
-		{
 			"fieldname":"finance_book",
 			"label": __("Finance Book"),
 			"fieldtype": "Link",
@@ -102,6 +67,41 @@
 			}
 		},
 		{
+			"fieldname":"ageing_based_on",
+			"label": __("Ageing Based On"),
+			"fieldtype": "Select",
+			"options": 'Posting Date\nDue Date',
+			"default": "Due Date"
+		},
+		{
+			"fieldname":"range1",
+			"label": __("Ageing Range 1"),
+			"fieldtype": "Int",
+			"default": "30",
+			"reqd": 1
+		},
+		{
+			"fieldname":"range2",
+			"label": __("Ageing Range 2"),
+			"fieldtype": "Int",
+			"default": "60",
+			"reqd": 1
+		},
+		{
+			"fieldname":"range3",
+			"label": __("Ageing Range 3"),
+			"fieldtype": "Int",
+			"default": "90",
+			"reqd": 1
+		},
+		{
+			"fieldname":"range4",
+			"label": __("Ageing Range 4"),
+			"fieldtype": "Int",
+			"default": "120",
+			"reqd": 1
+		},
+		{
 			"fieldname":"customer_group",
 			"label": __("Customer Group"),
 			"fieldtype": "Link",
@@ -114,12 +114,6 @@
 			"options": "Payment Terms Template"
 		},
 		{
-			"fieldname":"territory",
-			"label": __("Territory"),
-			"fieldtype": "Link",
-			"options": "Territory"
-		},
-		{
 			"fieldname":"sales_partner",
 			"label": __("Sales Partner"),
 			"fieldtype": "Link",
@@ -132,6 +126,12 @@
 			"options": "Sales Person"
 		},
 		{
+			"fieldname":"territory",
+			"label": __("Territory"),
+			"fieldtype": "Link",
+			"options": "Territory"
+		},
+		{
 			"fieldname": "group_by_party",
 			"label": __("Group By Customer"),
 			"fieldtype": "Check"
diff --git a/erpnext/accounts/report/cash_flow/custom_cash_flow.py b/erpnext/accounts/report/cash_flow/custom_cash_flow.py
index 8566f53..fe2bc72 100644
--- a/erpnext/accounts/report/cash_flow/custom_cash_flow.py
+++ b/erpnext/accounts/report/cash_flow/custom_cash_flow.py
@@ -334,10 +334,9 @@
 
 def execute(filters=None):
 	if not filters.periodicity: filters.periodicity = "Monthly"
-	period_list = get_period_list(
-		filters.from_fiscal_year, filters.to_fiscal_year, filters.periodicity,
-		filters.accumulated_values, filters.company
-	)
+	period_list = get_period_list(filters.from_fiscal_year, filters.to_fiscal_year,
+		filters.period_start_date, filters.period_end_date, filters.filter_based_on,
+		filters.periodicity, company=filters.company)
 
 	mappers = get_mappers_from_db()
 
@@ -396,7 +395,7 @@
 			gl_sum = frappe.db.sql_list("""
 				select sum(credit) - sum(debit)
 				from `tabGL Entry`
-				where company=%s and posting_date >= %s and posting_date <= %s 
+				where company=%s and posting_date >= %s and posting_date <= %s
 					and voucher_type != 'Period Closing Voucher'
 					and account in ( SELECT name FROM tabAccount WHERE name IN (%s)
 					OR parent_account IN (%s))
@@ -405,7 +404,7 @@
 			gl_sum = frappe.db.sql_list("""
 				select sum(credit) - sum(debit)
 				from `tabGL Entry`
-				where company=%s and posting_date >= %s and posting_date <= %s 
+				where company=%s and posting_date >= %s and posting_date <= %s
 					and voucher_type != 'Period Closing Voucher'
 					and account in ( SELECT name FROM tabAccount WHERE name IN (%s)
 					OR parent_account IN (%s))
diff --git a/erpnext/accounts/report/financial_statements.html b/erpnext/accounts/report/financial_statements.html
index 50947ec..2bb09cf 100644
--- a/erpnext/accounts/report/financial_statements.html
+++ b/erpnext/accounts/report/financial_statements.html
@@ -44,7 +44,7 @@
 		</tr>
 	</thead>
 	<tbody>
-		{% for(let j=0, k=data.length-1; j<k; j++) { %}
+		{% for(let j=0, k=data.length; j<k; j++) { %}
 			{%
 				var row = data[j];
 				var row_class = data[j].parent_account ? "" : "financial-statements-important";
diff --git a/erpnext/accounts/report/financial_statements.py b/erpnext/accounts/report/financial_statements.py
index 533685d..3785ebf 100644
--- a/erpnext/accounts/report/financial_statements.py
+++ b/erpnext/accounts/report/financial_statements.py
@@ -8,6 +8,7 @@
 import re
 from past.builtins import cmp
 import functools
+import math
 
 import frappe, erpnext
 from erpnext.accounts.report.utils import get_currency, convert_to_presentation_currency
@@ -45,10 +46,7 @@
 	start_date = year_start_date
 	months = get_months(year_start_date, year_end_date)
 
-	if (months // months_to_add) != (months / months_to_add):
-		months += months_to_add
-
-	for i in range(months // months_to_add):
+	for i in range(math.ceil(months / months_to_add)):
 		period = frappe._dict({
 			"from_date": start_date
 		})
@@ -405,12 +403,12 @@
 				FROM `tabDistributed Cost Center`
 				WHERE cost_center IN %(cost_center)s
 				AND parent NOT IN %(cost_center)s
-				AND is_cancelled = 0
 				GROUP BY parent
 			) as DCC_allocation
 			WHERE company=%(company)s
 			{additional_conditions}
 			AND posting_date <= %(to_date)s
+			AND is_cancelled = 0
 			AND cost_center = DCC_allocation.parent
 			""".format(additional_conditions=additional_conditions.replace("and cost_center in %(cost_center)s ", ''))
 
diff --git a/erpnext/accounts/report/trial_balance/trial_balance.py b/erpnext/accounts/report/trial_balance/trial_balance.py
index 5a699b6..3cf0870 100644
--- a/erpnext/accounts/report/trial_balance/trial_balance.py
+++ b/erpnext/accounts/report/trial_balance/trial_balance.py
@@ -152,6 +152,7 @@
 			{additional_conditions}
 			and (posting_date < %(from_date)s or ifnull(is_opening, 'No') = 'Yes')
 			and account in (select name from `tabAccount` where report_type=%(report_type)s)
+			and is_cancelled = 0
 		group by account""".format(additional_conditions=additional_conditions), query_filters , as_dict=True)
 
 	opening = frappe._dict()
diff --git a/erpnext/accounts/utils.py b/erpnext/accounts/utils.py
index 16146f4..824b2f2 100644
--- a/erpnext/accounts/utils.py
+++ b/erpnext/accounts/utils.py
@@ -133,7 +133,7 @@
 		acc = frappe.get_doc("Account", account)
 
 	try:
-		year_start_date = get_fiscal_year(date, verbose=0)[1]
+		year_start_date = get_fiscal_year(date, company=company, verbose=0)[1]
 	except FiscalYearError:
 		if getdate(date) > getdate(nowdate()):
 			# if fiscal year not found and the date is greater than today
@@ -144,14 +144,12 @@
 			# hence, assuming balance as 0.0
 			return 0.0
 
-	allow_cost_center_in_entry_of_bs_account = get_allow_cost_center_in_entry_of_bs_account()
-
 	if account:
 		report_type = acc.report_type
 	else:
 		report_type = ""
 
-	if cost_center and (allow_cost_center_in_entry_of_bs_account or report_type =='Profit and Loss'):
+	if cost_center and report_type == 'Profit and Loss':
 		cc = frappe.get_doc("Cost Center", cost_center)
 		if cc.is_group:
 			cond.append(""" exists (
@@ -678,7 +676,8 @@
 	invoice_list = frappe.db.sql("""
 		select
 			voucher_no, voucher_type, posting_date, due_date,
-			ifnull(sum({dr_or_cr}), 0) as invoice_amount
+			ifnull(sum({dr_or_cr}), 0) as invoice_amount,
+			account_currency as currency
 		from
 			`tabGL Entry`
 		where
@@ -735,7 +734,8 @@
 						'invoice_amount': flt(d.invoice_amount),
 						'payment_amount': payment_amount,
 						'outstanding_amount': outstanding_amount,
-						'due_date': d.due_date
+						'due_date': d.due_date,
+						'currency': d.currency
 					})
 				)
 
@@ -787,10 +787,10 @@
 		company_currency = frappe.get_cached_value('Company',  company,  "default_currency")
 		for each in acc:
 			each["company_currency"] = company_currency
-			each["balance"] = flt(get_balance_on(each.get("value"), in_account_currency=False))
+			each["balance"] = flt(get_balance_on(each.get("value"), in_account_currency=False, company=company))
 
 			if each.account_currency != company_currency:
-				each["balance_in_account_currency"] = flt(get_balance_on(each.get("value")))
+				each["balance_in_account_currency"] = flt(get_balance_on(each.get("value"), company=company))
 
 	return acc
 
@@ -897,11 +897,6 @@
 
 	return accounts
 
-def get_allow_cost_center_in_entry_of_bs_account():
-	def generator():
-		return cint(frappe.db.get_value('Accounts Settings', None, 'allow_cost_center_in_entry_of_bs_account'))
-	return frappe.local_cache("get_allow_cost_center_in_entry_of_bs_account", (), generator, regenerate_if_none=True)
-
 def get_stock_accounts(company):
 	return frappe.get_all("Account", filters = {
 		"account_type": "Stock",
diff --git a/erpnext/assets/desk_page/assets/assets.json b/erpnext/assets/desk_page/assets/assets.json
index 94939fd..449a5fa 100644
--- a/erpnext/assets/desk_page/assets/assets.json
+++ b/erpnext/assets/desk_page/assets/assets.json
@@ -58,7 +58,7 @@
    "type": "Report"
   },
   {
-   "label": "Assets Dashboard",
+   "label": "Dashboard",
    "link_to": "Asset",
    "type": "Dashboard"
   }
diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py
index 2ecabe6..0bd03a8 100644
--- a/erpnext/assets/doctype/asset/asset.py
+++ b/erpnext/assets/doctype/asset/asset.py
@@ -35,11 +35,9 @@
 		if not self.booked_fixed_asset and self.validate_make_gl_entry():
 			self.make_gl_entries()
 
-	def before_cancel(self):
-		self.cancel_auto_gen_movement()
-
 	def on_cancel(self):
 		self.validate_cancellation()
+		self.cancel_movement_entries()
 		self.delete_depreciation_entries()
 		self.set_status()
 		self.ignore_linked_doctypes = ('GL Entry', 'Stock Ledger Entry')
@@ -134,19 +132,6 @@
 				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(
-			"""SELECT asm.name, asm.docstatus
-			FROM `tabAsset Movement` asm, `tabAsset Movement Item` asm_item
-			WHERE asm_item.parent=asm.name and asm_item.asset=%s and asm.docstatus=1""", self.name, as_dict=1)
-		if len(movements) > 1:
-			frappe.throw(_('Asset has multiple Asset Movement Entries which has to be \
-				cancelled manually to cancel this asset.'))
-		if movements:
-			movement = frappe.get_doc('Asset Movement', movements[0].get('name'))
-			movement.flags.ignore_validate = True
-			movement.cancel()
-
 	def make_asset_movement(self):
 		reference_doctype = 'Purchase Receipt' if self.purchase_receipt else 'Purchase Invoice'
 		reference_docname = self.purchase_receipt or self.purchase_invoice
@@ -408,9 +393,21 @@
 					row.expected_value_after_useful_life = asset_value_after_full_schedule
 
 	def validate_cancellation(self):
+		if self.status in ("In Maintenance", "Out of Order"):
+			frappe.throw(_("There are active maintenance or repairs against the asset. You must complete all of them before cancelling the asset."))
 		if self.status not in ("Submitted", "Partially Depreciated", "Fully Depreciated"):
 			frappe.throw(_("Asset cannot be cancelled, as it is already {0}").format(self.status))
 
+	def cancel_movement_entries(self):
+		movements = frappe.db.sql(
+			"""SELECT asm.name, asm.docstatus
+			FROM `tabAsset Movement` asm, `tabAsset Movement Item` asm_item
+			WHERE asm_item.parent=asm.name and asm_item.asset=%s and asm.docstatus=1""", self.name, as_dict=1)
+
+		for movement in movements:
+			movement = frappe.get_doc('Asset Movement', movement.get('name'))
+			movement.cancel()
+
 	def delete_depreciation_entries(self):
 		for d in self.get("schedules"):
 			if d.journal_entry:
diff --git a/erpnext/assets/doctype/asset/depreciation.py b/erpnext/assets/doctype/asset/depreciation.py
index 522c1fe..8f0afb4 100644
--- a/erpnext/assets/doctype/asset/depreciation.py
+++ b/erpnext/assets/doctype/asset/depreciation.py
@@ -10,7 +10,7 @@
 
 def post_depreciation_entries(date=None):
 	# Return if automatic booking of asset depreciation is disabled
-	if not cint(frappe.db.get_single_value("Accounts Settings", "book_asset_depreciation_entry_automatically")):
+	if not cint(frappe.db.get_value("Accounts Settings", None, "book_asset_depreciation_entry_automatically")):
 		return
 
 	if not date:
@@ -58,7 +58,8 @@
 				"account": accumulated_depreciation_account,
 				"credit_in_account_currency": d.depreciation_amount,
 				"reference_type": "Asset",
-				"reference_name": asset.name
+				"reference_name": asset.name,
+				"cost_center": ""
 			}
 
 			debit_entry = {
@@ -196,12 +197,14 @@
 		{
 			"account": fixed_asset_account,
 			"credit_in_account_currency": asset.gross_purchase_amount,
-			"credit": asset.gross_purchase_amount
+			"credit": asset.gross_purchase_amount,
+			"cost_center": depreciation_cost_center
 		},
 		{
 			"account": accumulated_depr_account,
 			"debit_in_account_currency": accumulated_depr_amount,
-			"debit": accumulated_depr_amount
+			"debit": accumulated_depr_amount,
+			"cost_center": depreciation_cost_center
 		}
 	]
 
diff --git a/erpnext/assets/doctype/asset_movement/asset_movement.py b/erpnext/assets/doctype/asset_movement/asset_movement.py
index 3da355e..b2de250 100644
--- a/erpnext/assets/doctype/asset_movement/asset_movement.py
+++ b/erpnext/assets/doctype/asset_movement/asset_movement.py
@@ -87,33 +87,9 @@
 
 	def on_submit(self):
 		self.set_latest_location_in_asset()
-	
-	def before_cancel(self):
-		self.validate_last_movement()
 		
 	def on_cancel(self):
 		self.set_latest_location_in_asset()
-	
-	def validate_last_movement(self):
-		for d in self.assets:
-			auto_gen_movement_entry = frappe.db.sql(
-				"""
-				SELECT asm.name
-				FROM  `tabAsset Movement Item` asm_item, `tabAsset Movement` asm
-				WHERE 
-					asm.docstatus=1 and
-					asm_item.parent=asm.name and
-					asm_item.asset=%s and
-					asm.company=%s and
-					asm_item.source_location is NULL and
-					asm.purpose=%s
-				ORDER BY
-					asm.transaction_date asc
-				""", (d.asset, self.company, 'Receipt'), as_dict=1)
-
-			if auto_gen_movement_entry and auto_gen_movement_entry[0].get('name') == self.name:
-				frappe.throw(_('{0} will be cancelled automatically on asset cancellation as it was \
-					auto generated for Asset {1}').format(self.name, d.asset))
 
 	def set_latest_location_in_asset(self):
 		current_location, current_employee = '', ''
diff --git a/erpnext/assets/module_onboarding/assets/assets.json b/erpnext/assets/module_onboarding/assets/assets.json
index 66dd60a..1086ab4 100644
--- a/erpnext/assets/module_onboarding/assets/assets.json
+++ b/erpnext/assets/module_onboarding/assets/assets.json
@@ -13,7 +13,7 @@
  "documentation_url": "https://docs.erpnext.com/docs/user/manual/en/asset",
  "idx": 0,
  "is_complete": 0,
- "modified": "2020-05-08 16:17:31.685943",
+ "modified": "2020-07-08 14:05:51.828497",
  "modified_by": "Administrator",
  "module": "Assets",
  "name": "Assets",
@@ -27,7 +27,7 @@
   },
   {
    "step": "Create an Asset Category"
-  }, 
+  },
   {
    "step": "Purchase an Asset Item"
   },
@@ -35,8 +35,7 @@
    "step": "Create an Asset"
   }
  ],
- "subtitle": "Assets, Depreciations, Repairs and more",
- "success_message": "The Asset Module is all set up!",
- "title": "Let's Setup Asset Management",
- "user_can_dismiss": 1
+ "subtitle": "Assets, Depreciations, Repairs, and more.",
+ "success_message": "The Assets Module is all set up!",
+ "title": "Let's Set Up the Assets Module."
 }
\ No newline at end of file
diff --git a/erpnext/assets/onboarding_step/create_a_fixed_asset_item/create_a_fixed_asset_item.json b/erpnext/assets/onboarding_step/create_a_fixed_asset_item/create_a_fixed_asset_item.json
index f5818c0..51702d9 100644
--- a/erpnext/assets/onboarding_step/create_a_fixed_asset_item/create_a_fixed_asset_item.json
+++ b/erpnext/assets/onboarding_step/create_a_fixed_asset_item/create_a_fixed_asset_item.json
@@ -6,11 +6,14 @@
  "idx": 0,
  "is_complete": 0,
  "is_mandatory": 0,
+ "is_single": 0,
  "is_skipped": 0,
  "modified": "2020-05-08 13:20:00.259985",
  "modified_by": "Administrator",
  "name": "Create a Fixed Asset Item",
  "owner": "Administrator",
  "reference_document": "Item",
- "title": "Create a Fixed Asset Item"
+ "show_full_form": 0,
+ "title": "Create a Fixed Asset Item",
+ "validate_action": 0
 }
\ No newline at end of file
diff --git a/erpnext/assets/onboarding_step/create_an_asset/create_an_asset.json b/erpnext/assets/onboarding_step/create_an_asset/create_an_asset.json
index 5488b1d..b4f8a05 100644
--- a/erpnext/assets/onboarding_step/create_an_asset/create_an_asset.json
+++ b/erpnext/assets/onboarding_step/create_an_asset/create_an_asset.json
@@ -6,11 +6,14 @@
  "idx": 0,
  "is_complete": 0,
  "is_mandatory": 0,
+ "is_single": 0,
  "is_skipped": 0,
  "modified": "2020-05-08 13:21:53.332538",
  "modified_by": "Administrator",
  "name": "Create an Asset",
  "owner": "Administrator",
  "reference_document": "Asset",
- "title": "Create an Asset"
+ "show_full_form": 0,
+ "title": "Create an Asset",
+ "validate_action": 0
 }
\ No newline at end of file
diff --git a/erpnext/assets/onboarding_step/create_an_asset_category/create_an_asset_category.json b/erpnext/assets/onboarding_step/create_an_asset_category/create_an_asset_category.json
index 3bf54af..ffdb954 100644
--- a/erpnext/assets/onboarding_step/create_an_asset_category/create_an_asset_category.json
+++ b/erpnext/assets/onboarding_step/create_an_asset_category/create_an_asset_category.json
@@ -1,16 +1,19 @@
 {
-    "action": "Create Entry",
-    "creation": "2020-05-08 13:21:53.332538",
-    "docstatus": 0,
-    "doctype": "Onboarding Step",
-    "idx": 0,
-    "is_complete": 0,
-    "is_mandatory": 0,
-    "is_skipped": 0,
-    "modified": "2020-05-08 13:21:53.332538",
-    "modified_by": "Administrator",
-    "name": "Create an Asset Category",
-    "owner": "Administrator",
-    "reference_document": "Asset Category",
-    "title": "Create an Asset Category"
-   }
\ No newline at end of file
+ "action": "Create Entry",
+ "creation": "2020-05-08 13:21:53.332538",
+ "docstatus": 0,
+ "doctype": "Onboarding Step",
+ "idx": 0,
+ "is_complete": 0,
+ "is_mandatory": 0,
+ "is_single": 0,
+ "is_skipped": 0,
+ "modified": "2020-05-08 13:21:53.332538",
+ "modified_by": "Administrator",
+ "name": "Create an Asset Category",
+ "owner": "Administrator",
+ "reference_document": "Asset Category",
+ "show_full_form": 0,
+ "title": "Create an Asset Category",
+ "validate_action": 0
+}
\ No newline at end of file
diff --git a/erpnext/assets/onboarding_step/introduction_to_assets/introduction_to_assets.json b/erpnext/assets/onboarding_step/introduction_to_assets/introduction_to_assets.json
index d48dd1c..d89da27 100644
--- a/erpnext/assets/onboarding_step/introduction_to_assets/introduction_to_assets.json
+++ b/erpnext/assets/onboarding_step/introduction_to_assets/introduction_to_assets.json
@@ -6,11 +6,14 @@
  "idx": 0,
  "is_complete": 0,
  "is_mandatory": 0,
+ "is_single": 0,
  "is_skipped": 0,
  "modified": "2020-05-08 16:06:16.625646",
  "modified_by": "Administrator",
  "name": "Introduction to Assets",
  "owner": "Administrator",
+ "show_full_form": 0,
  "title": "Introduction to Assets",
+ "validate_action": 0,
  "video_url": "https://www.youtube.com/watch?v=I-K8pLRmvSo"
 }
\ No newline at end of file
diff --git a/erpnext/assets/onboarding_step/purchase_an_asset_item/purchase_an_asset_item.json b/erpnext/assets/onboarding_step/purchase_an_asset_item/purchase_an_asset_item.json
index 732ff7f..ce3185e 100644
--- a/erpnext/assets/onboarding_step/purchase_an_asset_item/purchase_an_asset_item.json
+++ b/erpnext/assets/onboarding_step/purchase_an_asset_item/purchase_an_asset_item.json
@@ -6,11 +6,14 @@
  "idx": 0,
  "is_complete": 0,
  "is_mandatory": 0,
+ "is_single": 0,
  "is_skipped": 0,
  "modified": "2020-05-08 13:21:28.208059",
  "modified_by": "Administrator",
  "name": "Purchase an Asset Item",
  "owner": "Administrator",
  "reference_document": "Purchase Receipt",
- "title": "Purchase an Asset Item"
+ "show_full_form": 0,
+ "title": "Purchase an Asset Item",
+ "validate_action": 0
 }
\ No newline at end of file
diff --git a/erpnext/buying/buying_dashboard/buying/buying.json b/erpnext/buying/buying_dashboard/buying/buying.json
new file mode 100644
index 0000000..ab7ebac
--- /dev/null
+++ b/erpnext/buying/buying_dashboard/buying/buying.json
@@ -0,0 +1,46 @@
+{
+ "cards": [
+  {
+   "card": "Annual Purchase"
+  },
+  {
+   "card": "Purchase Orders to Receive"
+  },
+  {
+   "card": "Purchase Orders to Bill"
+  },
+  {
+   "card": "Active Suppliers"
+  }
+ ],
+ "charts": [
+  {
+   "chart": "Purchase Order Trends",
+   "width": "Full"
+  },
+  {
+   "chart": "Material Request Analysis",
+   "width": "Half"
+  },
+  {
+   "chart": "Purchase Order Analysis",
+   "width": "Half"
+  },
+  {
+   "chart": "Top Suppliers",
+   "width": "Full"
+  }
+ ],
+ "creation": "2020-07-20 21:01:02.541065",
+ "dashboard_name": "Buying",
+ "docstatus": 0,
+ "doctype": "Dashboard",
+ "idx": 0,
+ "is_default": 1,
+ "is_standard": 1,
+ "modified": "2020-07-22 12:48:38.112744",
+ "modified_by": "Administrator",
+ "module": "Buying",
+ "name": "Buying",
+ "owner": "Administrator"
+}
\ No newline at end of file
diff --git a/erpnext/buying/dashboard_chart/material_request_analysis/material_request_analysis.json b/erpnext/buying/dashboard_chart/material_request_analysis/material_request_analysis.json
new file mode 100644
index 0000000..0b66f1f
--- /dev/null
+++ b/erpnext/buying/dashboard_chart/material_request_analysis/material_request_analysis.json
@@ -0,0 +1,27 @@
+{
+ "chart_name": "Material Request Analysis",
+ "chart_type": "Group By",
+ "creation": "2020-07-20 21:01:02.242563",
+ "custom_options": "{\"height\": 300}",
+ "docstatus": 0,
+ "doctype": "Dashboard Chart",
+ "document_type": "Material Request",
+ "dynamic_filters_json": "[[\"Material Request\",\"company\",\"=\",\"frappe.defaults.get_user_default(\\\"Company\\\")\"]]",
+ "filters_json": "[[\"Material Request\",\"status\",\"not in\",[\"Draft\",\"Cancelled\",\"Stopped\",null],false],[\"Material Request\",\"material_request_type\",\"=\",\"Purchase\",false],[\"Material Request\",\"docstatus\",\"=\",\"1\",false],[\"Material Request\",\"transaction_date\",\"Timespan\",\"last quarter\",false]]",
+ "group_by_based_on": "status",
+ "group_by_type": "Count",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "last_synced_on": "2020-07-22 12:43:56.961250",
+ "modified": "2020-07-22 21:20:51.840194",
+ "modified_by": "Administrator",
+ "module": "Buying",
+ "name": "Material Request Analysis",
+ "number_of_groups": 0,
+ "owner": "Administrator",
+ "timeseries": 0,
+ "type": "Donut",
+ "use_report_chart": 0,
+ "y_axis": []
+}
\ No newline at end of file
diff --git a/erpnext/buying/dashboard_chart/purchase_order_analysis/purchase_order_analysis.json b/erpnext/buying/dashboard_chart/purchase_order_analysis/purchase_order_analysis.json
new file mode 100644
index 0000000..020755b
--- /dev/null
+++ b/erpnext/buying/dashboard_chart/purchase_order_analysis/purchase_order_analysis.json
@@ -0,0 +1,24 @@
+{
+ "chart_name": "Purchase Order Analysis",
+ "chart_type": "Report",
+ "creation": "2020-07-20 21:01:02.203880",
+ "custom_options": "{\"type\": \"donut\", \"height\": 300, \"axisOptions\": {\"shortenYAxisNumbers\": 1}}",
+ "docstatus": 0,
+ "doctype": "Dashboard Chart",
+ "dynamic_filters_json": "{\"company\":\"frappe.defaults.get_user_default(\\\"Company\\\")\",\"from_date\":\"frappe.datetime.add_months(frappe.datetime.nowdate(), -1)\",\"to_date\":\"frappe.datetime.nowdate()\"}",
+ "filters_json": "{\"group_by_po\":0}",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "modified": "2020-07-22 12:44:35.754973",
+ "modified_by": "Administrator",
+ "module": "Buying",
+ "name": "Purchase Order Analysis",
+ "number_of_groups": 0,
+ "owner": "Administrator",
+ "report_name": "Purchase Order Analysis",
+ "timeseries": 0,
+ "type": "Donut",
+ "use_report_chart": 1,
+ "y_axis": []
+}
\ No newline at end of file
diff --git a/erpnext/buying/dashboard_chart/purchase_order_trends/purchase_order_trends.json b/erpnext/buying/dashboard_chart/purchase_order_trends/purchase_order_trends.json
new file mode 100644
index 0000000..6452ed2
--- /dev/null
+++ b/erpnext/buying/dashboard_chart/purchase_order_trends/purchase_order_trends.json
@@ -0,0 +1,24 @@
+{
+ "chart_name": "Purchase Order Trends",
+ "chart_type": "Report",
+ "creation": "2020-07-20 21:01:02.295012",
+ "custom_options": "{\"type\": \"line\", \"axisOptions\": {\"shortenYAxisNumbers\": 1}, \"tooltipOptions\": {}, \"lineOptions\": {\"regionFill\": 1}}",
+ "docstatus": 0,
+ "doctype": "Dashboard Chart",
+ "dynamic_filters_json": "{\"company\":\"frappe.defaults.get_user_default(\\\"Company\\\")\",\"fiscal_year\":\"frappe.sys_defaults.fiscal_year\"}",
+ "filters_json": "{\"period\":\"Monthly\",\"period_based_on\":\"posting_date\",\"based_on\":\"Item\"}",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "modified": "2020-07-21 16:13:25.092287",
+ "modified_by": "Administrator",
+ "module": "Buying",
+ "name": "Purchase Order Trends",
+ "number_of_groups": 0,
+ "owner": "Administrator",
+ "report_name": "Purchase Order Trends",
+ "timeseries": 0,
+ "type": "Line",
+ "use_report_chart": 1,
+ "y_axis": []
+}
\ No newline at end of file
diff --git a/erpnext/buying/dashboard_chart/top_suppliers/top_suppliers.json b/erpnext/buying/dashboard_chart/top_suppliers/top_suppliers.json
new file mode 100644
index 0000000..6f7da8e
--- /dev/null
+++ b/erpnext/buying/dashboard_chart/top_suppliers/top_suppliers.json
@@ -0,0 +1,23 @@
+{
+ "chart_name": "Top Suppliers",
+ "chart_type": "Report",
+ "creation": "2020-07-20 21:01:02.329519",
+ "docstatus": 0,
+ "doctype": "Dashboard Chart",
+ "dynamic_filters_json": "{\"company\":\"frappe.defaults.get_user_default(\\\"Company\\\")\",\"fiscal_year\":\"frappe.sys_defaults.fiscal_year\"}",
+ "filters_json": "{\"period\":\"Monthly\",\"period_based_on\":\"posting_date\",\"based_on\":\"Supplier\"}",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "modified": "2020-07-22 12:43:40.829652",
+ "modified_by": "Administrator",
+ "module": "Buying",
+ "name": "Top Suppliers",
+ "number_of_groups": 0,
+ "owner": "Administrator",
+ "report_name": "Purchase Receipt Trends",
+ "timeseries": 0,
+ "type": "Bar",
+ "use_report_chart": 1,
+ "y_axis": []
+}
\ No newline at end of file
diff --git a/erpnext/buying/dashboard_fixtures.py b/erpnext/buying/dashboard_fixtures.py
deleted file mode 100644
index c6e2ffa..0000000
--- a/erpnext/buying/dashboard_fixtures.py
+++ /dev/null
@@ -1,211 +0,0 @@
-# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-import frappe
-import json
-from frappe import _
-from frappe.utils import nowdate
-from erpnext.accounts.dashboard_fixtures import _get_fiscal_year
-
-def get_data():
-
-	fiscal_year = _get_fiscal_year(nowdate())
-
-	if not fiscal_year:
-		return frappe._dict()
-
-	company = frappe.get_doc("Company", get_company_for_dashboards())
-	fiscal_year_name = fiscal_year.get("name")
-	start_date = str(fiscal_year.get("year_start_date"))
-	end_date = str(fiscal_year.get("year_end_date"))
-
-	return frappe._dict({
-		"dashboards": get_dashboards(),
-		"charts": get_charts(company, fiscal_year_name, start_date, end_date),
-		"number_cards": get_number_cards(company, fiscal_year_name, start_date, end_date),
-	})
-
-def get_company_for_dashboards():
-	company = frappe.defaults.get_defaults().company
-	if company:
-		return company
-	else:
-		company_list = frappe.get_list("Company")
-		if company_list:
-			return company_list[0].name
-	return None
-
-def get_dashboards():
-	return [{
-		"name": "Buying",
-		"dashboard_name": "Buying",
-		"charts": [
-			{ "chart": "Purchase Order Trends", "width": "Full"},
-			{ "chart": "Material Request Analysis", "width": "Half"},
-			{ "chart": "Purchase Order Analysis", "width": "Half"},
-			{ "chart": "Top Suppliers", "width": "Full"}
-		],
-		"cards": [
-			{ "card": "Annual Purchase"},
-			{ "card": "Purchase Orders to Receive"},
-			{ "card": "Purchase Orders to Bill"},
-			{ "card": "Active Suppliers"}
-		]
-	}]
-
-def get_charts(company, fiscal_year_name, start_date, end_date):
-	return [
-		{
-			"name": "Purchase Order Analysis",
-			"chart_name": _("Purchase Order Analysis"),
-			"chart_type": "Report",
-			"custom_options": json.dumps({
-				"type": "donut",
-				"height": 300,
-				"axisOptions": {"shortenYAxisNumbers": 1}
-			}),
-			"doctype": "Dashboard Chart",
-			"filters_json": json.dumps({
-				"company": company.name,
-				"from_date": start_date,
-				"to_date": end_date
-			}),
-			"is_custom": 1,
-			"is_public": 1,
-			"owner": "Administrator",
-			"report_name": "Purchase Order Analysis",
-			"type": "Donut"
-		},
-		{
-			"name": "Material Request Analysis",
-			"chart_name": _("Material Request Analysis"),
-			"chart_type": "Group By",
-			"custom_options": json.dumps({"height": 300}),
-			"doctype": "Dashboard Chart",
-			"document_type": "Material Request",
-			"filters_json": json.dumps(
-				[["Material Request", "status", "not in", ["Draft", "Cancelled", "Stopped", None], False],
-				["Material Request", "material_request_type", "=", "Purchase", False],
-				["Material Request", "company", "=", company.name, False],
-				["Material Request", "docstatus", "=", 1, False],
-				["Material Request", "transaction_date", "Between", [start_date, end_date], False]]
-			),
-			"group_by_based_on": "status",
-			"group_by_type": "Count",
-			"is_custom": 0,
-			"is_public": 1,
-			"number_of_groups": 0,
-			"owner": "Administrator",
-			"type": "Donut"
-		},
-		{
-			"name": "Purchase Order Trends",
-			"chart_name": _("Purchase Order Trends"),
-			"chart_type": "Report",
-			"custom_options": json.dumps({
-				"type": "line",
-				"axisOptions": {"shortenYAxisNumbers": 1},
-				"tooltipOptions": {},
-				"lineOptions": {
-					"regionFill": 1
-				}
-			}),
-			"doctype": "Dashboard Chart",
-			"filters_json": json.dumps({
-				"company": company.name,
-				"period": "Monthly",
-				"fiscal_year": fiscal_year_name,
-				"period_based_on": "posting_date",
-				"based_on": "Item"
-			}),
-			"is_custom": 1,
-			"is_public": 1,
-			"owner": "Administrator",
-			"report_name": "Purchase Order Trends",
-			"type": "Line"
-		},
-		{
-			"name": "Top Suppliers",
-			"chart_name": _("Top Suppliers"),
-			"chart_type": "Report",
-			"doctype": "Dashboard Chart",
-			"filters_json": json.dumps({
-				"company": company.name,
-				"period": "Monthly",
-				"fiscal_year": fiscal_year_name,
-				"period_based_on": "posting_date",
-				"based_on": "Supplier"
-			}),
-			"is_custom": 1,
-			"is_public": 1,
-			"owner": "Administrator",
-			"report_name": "Purchase Receipt Trends",
-			"type": "Bar"
-		}
- 	]
-
-def get_number_cards(company, fiscal_year_name, start_date, end_date):
-	return [
-		{
-			"name": "Annual Purchase",
-			"aggregate_function_based_on": "base_net_total",
-			"doctype": "Number Card",
-			"document_type": "Purchase Order",
-			"filters_json": json.dumps([
-				["Purchase Order", "transaction_date", "Between", [start_date, end_date], False],
-				["Purchase Order", "status", "not in", ["Draft", "Cancelled", "Closed", None], False],
-				["Purchase Order", "docstatus", "=", 1, False],
-				["Purchase Order", "company", "=", company.name, False]
-			]),
-			"function": "Sum",
-			"is_public": 1,
-			"label": _("Annual Purchase"),
-			"owner": "Administrator",
-			"show_percentage_stats": 1,
-			"stats_time_interval": "Monthly"
-		},
-		{
-			"name": "Purchase Orders to Receive",
-			"doctype": "Number Card",
-			"document_type": "Purchase Order",
-			"filters_json": json.dumps([
-				["Purchase Order", "status", "in", ["To Receive and Bill", "To Receive", None], False],
-				["Purchase Order", "docstatus", "=", 1, False],
-				["Purchase Order", "company", "=", company.name, False]
-			]),
-			"function": "Count",
-			"is_public": 1,
-			"label": _("Purchase Orders to Receive"),
-			"owner": "Administrator",
-			"show_percentage_stats": 1,
-			"stats_time_interval": "Weekly"
-		},
-		{
-			"name": "Purchase Orders to Bill",
-			"doctype": "Number Card",
-			"document_type": "Purchase Order",
-			"filters_json": json.dumps([
-				["Purchase Order", "status", "in", ["To Receive and Bill", "To Bill", None], False],
-				["Purchase Order", "docstatus", "=", 1, False],
-				["Purchase Order", "company", "=", company.name, False]
-			]),
-			"function": "Count",
-			"is_public": 1,
-			"label": _("Purchase Orders to Bill"),
-			"owner": "Administrator",
-			"show_percentage_stats": 1,
-			"stats_time_interval": "Weekly"
-		},
-		{
-			"name": "Active Suppliers",
-			"doctype": "Number Card",
-			"document_type": "Supplier",
-			"filters_json": json.dumps([["Supplier", "disabled", "=", "0"]]),
-			"function": "Count",
-			"is_public": 1,
-			"label": "Active Suppliers",
-			"owner": "Administrator",
-			"show_percentage_stats": 1,
-			"stats_time_interval": "Monthly"
-		}
-	]
\ No newline at end of file
diff --git a/erpnext/buying/desk_page/buying/buying.json b/erpnext/buying/desk_page/buying/buying.json
index bddb957..565d39c 100644
--- a/erpnext/buying/desk_page/buying/buying.json
+++ b/erpnext/buying/desk_page/buying/buying.json
@@ -33,7 +33,7 @@
   {
    "hidden": 0,
    "label": "Other Reports",
-   "links": "[\n    {\n        \"is_query_report\": true,\n        \"label\": \"Items To Be Requested\",\n        \"name\": \"Items To Be Requested\",\n        \"onboard\": 1,\n        \"reference_doctype\": \"Item\",\n        \"type\": \"report\"\n    },\n    {\n        \"is_query_report\": true,\n        \"label\": \"Item-wise Purchase History\",\n        \"name\": \"Item-wise Purchase History\",\n        \"onboard\": 1,\n        \"reference_doctype\": \"Item\",\n        \"type\": \"report\"\n    },\n    {\n        \"is_query_report\": true,\n        \"label\": \"Subcontracted Raw Materials To Be Transferred\",\n        \"name\": \"Subcontracted Raw Materials To Be Transferred\",\n        \"reference_doctype\": \"Purchase Order\",\n        \"type\": \"report\"\n    },\n    {\n        \"is_query_report\": true,\n        \"label\": \"Subcontracted Item To Be Received\",\n        \"name\": \"Subcontracted Item To Be Received\",\n        \"reference_doctype\": \"Purchase Order\",\n        \"type\": \"report\"\n    },\n    {\n        \"is_query_report\": true,\n        \"label\": \"Quoted Item Comparison\",\n        \"name\": \"Quoted Item Comparison\",\n         \"onboard\": 1,\n        \"reference_doctype\": \"Supplier Quotation\",\n        \"type\": \"report\"\n    },\n    {\n        \"is_query_report\": true,\n        \"label\": \"Material Requests for which Supplier Quotations are not created\",\n        \"name\": \"Material Requests for which Supplier Quotations are not created\",\n        \"reference_doctype\": \"Material Request\",\n        \"type\": \"report\"\n    },\n    {\n        \"is_query_report\": true,\n        \"label\": \"Supplier Addresses And Contacts\",\n        \"name\": \"Address And Contacts\",\n        \"reference_doctype\": \"Address\",\n        \"route_options\": {\n            \"party_type\": \"Supplier\"\n        },\n        \"type\": \"report\"\n    }\n]"
+   "links": "[\n    {\n        \"is_query_report\": true,\n        \"label\": \"Items To Be Requested\",\n        \"name\": \"Items To Be Requested\",\n        \"onboard\": 1,\n        \"reference_doctype\": \"Item\",\n        \"type\": \"report\"\n    },\n    {\n        \"is_query_report\": true,\n        \"label\": \"Item-wise Purchase History\",\n        \"name\": \"Item-wise Purchase History\",\n        \"onboard\": 1,\n        \"reference_doctype\": \"Item\",\n        \"type\": \"report\"\n    },\n    {\n        \"is_query_report\": true,\n        \"label\": \"Purchase Receipt Trends\",\n        \"name\": \"Purchase Receipt Trends\",\n        \"reference_doctype\": \"Purchase Receipt\",\n        \"type\": \"report\"\n    },\n    {\n        \"is_query_report\": true,\n        \"label\": \"Purchase Invoice Trends\",\n        \"name\": \"Purchase Invoice Trends\",\n        \"reference_doctype\": \"Purchase Invoice\",\n        \"type\": \"report\"\n    },\n    {\n        \"is_query_report\": true,\n        \"label\": \"Subcontracted Raw Materials To Be Transferred\",\n        \"name\": \"Subcontracted Raw Materials To Be Transferred\",\n        \"reference_doctype\": \"Purchase Order\",\n        \"type\": \"report\"\n    },\n    {\n        \"is_query_report\": true,\n        \"label\": \"Subcontracted Item To Be Received\",\n        \"name\": \"Subcontracted Item To Be Received\",\n        \"reference_doctype\": \"Purchase Order\",\n        \"type\": \"report\"\n    },\n    {\n        \"is_query_report\": true,\n        \"label\": \"Quoted Item Comparison\",\n        \"name\": \"Quoted Item Comparison\",\n         \"onboard\": 1,\n        \"reference_doctype\": \"Supplier Quotation\",\n        \"type\": \"report\"\n    },\n    {\n        \"is_query_report\": true,\n        \"label\": \"Material Requests for which Supplier Quotations are not created\",\n        \"name\": \"Material Requests for which Supplier Quotations are not created\",\n        \"reference_doctype\": \"Material Request\",\n        \"type\": \"report\"\n    },\n    {\n        \"is_query_report\": true,\n        \"label\": \"Supplier Addresses And Contacts\",\n        \"name\": \"Address And Contacts\",\n        \"reference_doctype\": \"Address\",\n        \"route_options\": {\n            \"party_type\": \"Supplier\"\n        },\n        \"type\": \"report\"\n    }\n]"
   },
   {
    "hidden": 0,
@@ -60,7 +60,7 @@
  "idx": 0,
  "is_standard": 1,
  "label": "Buying",
- "modified": "2020-05-28 13:32:49.960574",
+ "modified": "2020-06-29 19:30:24.983050",
  "modified_by": "Administrator",
  "module": "Buying",
  "name": "Buying",
diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.js b/erpnext/buying/doctype/purchase_order/purchase_order.js
index 4a8146a..25065ab 100644
--- a/erpnext/buying/doctype/purchase_order/purchase_order.js
+++ b/erpnext/buying/doctype/purchase_order/purchase_order.js
@@ -7,12 +7,6 @@
 
 frappe.ui.form.on("Purchase Order", {
 	setup: function(frm) {
-		frm.custom_make_buttons = {
-			'Purchase Receipt': 'Receipt',
-			'Purchase Invoice': 'Invoice',
-			'Stock Entry': 'Material to Supplier',
-			'Payment Entry': 'Payment'
-		}
 
 		frm.set_query("reserve_warehouse", "supplied_items", function() {
 			return {
@@ -36,20 +30,6 @@
 
 	},
 
-	refresh: function(frm) {
-		if(frm.doc.docstatus === 1 && frm.doc.status !== 'Closed'
-			&& flt(frm.doc.per_received) < 100 && flt(frm.doc.per_billed) < 100) {
-			frm.add_custom_button(__('Update Items'), () => {
-				erpnext.utils.update_child_items({
-					frm: frm,
-					child_docname: "items",
-					child_doctype: "Purchase Order Detail",
-					cannot_add_row: false,
-				})
-			});
-		}
-	},
-
 	onload: function(frm) {
 		set_schedule_date(frm);
 		if (!frm.doc.transaction_date){
@@ -76,6 +56,18 @@
 });
 
 erpnext.buying.PurchaseOrderController = erpnext.buying.BuyingController.extend({
+	setup: function() {
+		this.frm.custom_make_buttons = {
+			'Purchase Receipt': 'Receipt',
+			'Purchase Invoice': 'Invoice',
+			'Stock Entry': 'Material to Supplier',
+			'Payment Entry': 'Payment',
+		}
+
+		this._super();
+
+	},
+
 	refresh: function(doc, cdt, cdn) {
 		var me = this;
 		this._super();
@@ -99,6 +91,16 @@
 
 		if(doc.docstatus == 1) {
 			if(!in_list(["Closed", "Delivered"], doc.status)) {
+				if(this.frm.doc.status !== 'Closed' && flt(this.frm.doc.per_received) < 100 && flt(this.frm.doc.per_billed) < 100) {
+					this.frm.add_custom_button(__('Update Items'), () => {
+						erpnext.utils.update_child_items({
+							frm: frm,
+							child_docname: "items",
+							child_doctype: "Purchase Order Detail",
+							cannot_add_row: false,
+						})
+					});
+				}
 				if (this.frm.has_perm("submit")) {
 					if(flt(doc.per_billed, 6) < 100 || flt(doc.per_received, 6) < 100) {
 						if (doc.status != "On Hold") {
@@ -123,14 +125,14 @@
 			}
 			if(doc.status != "Closed") {
 				if (doc.status != "On Hold") {
-					if(flt(doc.per_received, 2) < 100 && allow_receipt) {
+					if(flt(doc.per_received) < 100 && allow_receipt) {
 						cur_frm.add_custom_button(__('Receipt'), this.make_purchase_receipt, __('Create'));
 						if(doc.is_subcontracted==="Yes" && me.has_unsupplied_items()) {
 							cur_frm.add_custom_button(__('Material to Supplier'),
 								function() { me.make_stock_entry(); }, __("Transfer"));
 						}
 					}
-					if(flt(doc.per_billed, 2) < 100)
+					if(flt(doc.per_billed) < 100)
 						cur_frm.add_custom_button(__('Invoice'),
 							this.make_purchase_invoice, __('Create'));
 
diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.json b/erpnext/buying/doctype/purchase_order/purchase_order.json
index 13f5cb0..502dbba 100644
--- a/erpnext/buying/doctype/purchase_order/purchase_order.json
+++ b/erpnext/buying/doctype/purchase_order/purchase_order.json
@@ -137,9 +137,7 @@
   {
    "fieldname": "supplier_section",
    "fieldtype": "Section Break",
-   "options": "fa fa-user",
-   "show_days": 1,
-   "show_seconds": 1
+   "options": "fa fa-user"
   },
   {
    "allow_on_submit": 1,
@@ -149,9 +147,7 @@
    "hidden": 1,
    "label": "Title",
    "no_copy": 1,
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "fieldname": "naming_series",
@@ -163,9 +159,7 @@
    "options": "PUR-ORD-.YYYY.-",
    "print_hide": 1,
    "reqd": 1,
-   "set_only_once": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "set_only_once": 1
   },
   {
    "bold": 1,
@@ -178,18 +172,14 @@
    "options": "Supplier",
    "print_hide": 1,
    "reqd": 1,
-   "search_index": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "search_index": 1
   },
   {
    "depends_on": "eval:doc.supplier && doc.docstatus===0 && (!(doc.items && doc.items.length) || (doc.items.length==1 && !doc.items[0].item_code))",
    "description": "Fetch items based on Default Supplier.",
    "fieldname": "get_items_from_open_material_requests",
    "fieldtype": "Button",
-   "label": "Get Items from Open Material Requests",
-   "show_days": 1,
-   "show_seconds": 1
+   "label": "Get Items from Open Material Requests"
   },
   {
    "bold": 1,
@@ -198,9 +188,7 @@
    "fieldtype": "Data",
    "in_global_search": 1,
    "label": "Supplier Name",
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "company",
@@ -212,17 +200,13 @@
    "options": "Company",
    "print_hide": 1,
    "remember_last_selected_value": 1,
-   "reqd": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "reqd": 1
   },
   {
    "fieldname": "column_break1",
    "fieldtype": "Column Break",
    "oldfieldtype": "Column Break",
    "print_width": "50%",
-   "show_days": 1,
-   "show_seconds": 1,
    "width": "50%"
   },
   {
@@ -234,35 +218,27 @@
    "oldfieldname": "transaction_date",
    "oldfieldtype": "Date",
    "reqd": 1,
-   "search_index": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "search_index": 1
   },
   {
    "allow_on_submit": 1,
    "fieldname": "schedule_date",
    "fieldtype": "Date",
-   "label": "Required By",
-   "show_days": 1,
-   "show_seconds": 1
+   "label": "Required By"
   },
   {
    "allow_on_submit": 1,
    "depends_on": "eval:doc.docstatus===1",
    "fieldname": "order_confirmation_no",
    "fieldtype": "Data",
-   "label": "Order Confirmation No",
-   "show_days": 1,
-   "show_seconds": 1
+   "label": "Order Confirmation No"
   },
   {
    "allow_on_submit": 1,
    "depends_on": "eval:doc.order_confirmation_no",
    "fieldname": "order_confirmation_date",
    "fieldtype": "Date",
-   "label": "Order Confirmation Date",
-   "show_days": 1,
-   "show_seconds": 1
+   "label": "Order Confirmation Date"
   },
   {
    "fieldname": "amended_from",
@@ -274,25 +250,19 @@
    "oldfieldtype": "Data",
    "options": "Purchase Order",
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "drop_ship",
    "fieldtype": "Section Break",
-   "label": "Drop Ship",
-   "show_days": 1,
-   "show_seconds": 1
+   "label": "Drop Ship"
   },
   {
    "fieldname": "customer",
    "fieldtype": "Link",
    "label": "Customer",
    "options": "Customer",
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "bold": 1,
@@ -300,41 +270,31 @@
    "fieldtype": "Data",
    "label": "Customer Name",
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "column_break_19",
-   "fieldtype": "Column Break",
-   "show_days": 1,
-   "show_seconds": 1
+   "fieldtype": "Column Break"
   },
   {
    "fieldname": "customer_contact_person",
    "fieldtype": "Link",
    "label": "Customer Contact",
-   "options": "Contact",
-   "show_days": 1,
-   "show_seconds": 1
+   "options": "Contact"
   },
   {
    "fieldname": "customer_contact_display",
    "fieldtype": "Small Text",
    "hidden": 1,
    "label": "Customer Contact",
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "fieldname": "customer_contact_mobile",
    "fieldtype": "Small Text",
    "hidden": 1,
    "label": "Customer Mobile No",
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "fieldname": "customer_contact_email",
@@ -342,60 +302,46 @@
    "hidden": 1,
    "label": "Customer Contact Email",
    "options": "Email",
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "collapsible": 1,
    "fieldname": "section_addresses",
    "fieldtype": "Section Break",
-   "label": "Address and Contact",
-   "show_days": 1,
-   "show_seconds": 1
+   "label": "Address and Contact"
   },
   {
    "fieldname": "supplier_address",
    "fieldtype": "Link",
    "label": "Select Supplier Address",
    "options": "Address",
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "fieldname": "contact_person",
    "fieldtype": "Link",
    "label": "Contact Person",
    "options": "Contact",
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "fieldname": "address_display",
    "fieldtype": "Small Text",
    "label": "Address",
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "contact_display",
    "fieldtype": "Small Text",
    "in_global_search": 1,
    "label": "Contact",
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "contact_mobile",
    "fieldtype": "Small Text",
    "label": "Mobile No",
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "contact_email",
@@ -403,42 +349,32 @@
    "label": "Contact Email",
    "options": "Email",
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "col_break_address",
-   "fieldtype": "Column Break",
-   "show_days": 1,
-   "show_seconds": 1
+   "fieldtype": "Column Break"
   },
   {
    "fieldname": "shipping_address",
    "fieldtype": "Link",
    "label": "Select Shipping Address",
    "options": "Address",
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "fieldname": "shipping_address_display",
    "fieldtype": "Small Text",
    "label": "Shipping Address",
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "collapsible": 1,
    "fieldname": "currency_and_price_list",
    "fieldtype": "Section Break",
    "label": "Currency and Price List",
-   "options": "fa fa-tag",
-   "show_days": 1,
-   "show_seconds": 1
+   "options": "fa fa-tag"
   },
   {
    "fieldname": "currency",
@@ -448,9 +384,7 @@
    "oldfieldtype": "Select",
    "options": "Currency",
    "print_hide": 1,
-   "reqd": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "reqd": 1
   },
   {
    "fieldname": "conversion_rate",
@@ -460,24 +394,18 @@
    "oldfieldtype": "Currency",
    "precision": "9",
    "print_hide": 1,
-   "reqd": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "reqd": 1
   },
   {
    "fieldname": "cb_price_list",
-   "fieldtype": "Column Break",
-   "show_days": 1,
-   "show_seconds": 1
+   "fieldtype": "Column Break"
   },
   {
    "fieldname": "buying_price_list",
    "fieldtype": "Link",
    "label": "Price List",
    "options": "Price List",
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "fieldname": "price_list_currency",
@@ -485,18 +413,14 @@
    "label": "Price List Currency",
    "options": "Currency",
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "plc_conversion_rate",
    "fieldtype": "Float",
    "label": "Price List Exchange Rate",
    "precision": "9",
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "default": "0",
@@ -505,15 +429,11 @@
    "label": "Ignore Pricing Rule",
    "no_copy": 1,
    "permlevel": 1,
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "fieldname": "sec_warehouse",
-   "fieldtype": "Section Break",
-   "show_days": 1,
-   "show_seconds": 1
+   "fieldtype": "Section Break"
   },
   {
    "description": "Sets 'Warehouse' in each row of the Items table.",
@@ -521,15 +441,11 @@
    "fieldtype": "Link",
    "label": "Set Target Warehouse",
    "options": "Warehouse",
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "fieldname": "col_break_warehouse",
-   "fieldtype": "Column Break",
-   "show_days": 1,
-   "show_seconds": 1
+   "fieldtype": "Column Break"
   },
   {
    "default": "No",
@@ -538,33 +454,25 @@
    "in_standard_filter": 1,
    "label": "Supply Raw Materials",
    "options": "No\nYes",
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "depends_on": "eval:doc.is_subcontracted==\"Yes\"",
    "fieldname": "supplier_warehouse",
    "fieldtype": "Link",
    "label": "Supplier Warehouse",
-   "options": "Warehouse",
-   "show_days": 1,
-   "show_seconds": 1
+   "options": "Warehouse"
   },
   {
    "fieldname": "items_section",
    "fieldtype": "Section Break",
    "oldfieldtype": "Section Break",
-   "options": "fa fa-shopping-cart",
-   "show_days": 1,
-   "show_seconds": 1
+   "options": "fa fa-shopping-cart"
   },
   {
    "fieldname": "scan_barcode",
    "fieldtype": "Data",
-   "label": "Scan Barcode",
-   "show_days": 1,
-   "show_seconds": 1
+   "label": "Scan Barcode"
   },
   {
    "allow_bulk_edit": 1,
@@ -574,34 +482,26 @@
    "oldfieldname": "po_details",
    "oldfieldtype": "Table",
    "options": "Purchase Order Item",
-   "reqd": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "reqd": 1
   },
   {
    "collapsible": 1,
    "fieldname": "section_break_48",
    "fieldtype": "Section Break",
-   "label": "Pricing Rules",
-   "show_days": 1,
-   "show_seconds": 1
+   "label": "Pricing Rules"
   },
   {
    "fieldname": "pricing_rules",
    "fieldtype": "Table",
    "label": "Purchase Order Pricing Rule",
    "options": "Pricing Rule Detail",
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "collapsible_depends_on": "supplied_items",
    "fieldname": "raw_material_details",
    "fieldtype": "Section Break",
-   "label": "Raw Materials Supplied",
-   "show_days": 1,
-   "show_seconds": 1
+   "label": "Raw Materials Supplied"
   },
   {
    "fieldname": "supplied_items",
@@ -611,23 +511,17 @@
    "oldfieldtype": "Table",
    "options": "Purchase Order Item Supplied",
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "sb_last_purchase",
-   "fieldtype": "Section Break",
-   "show_days": 1,
-   "show_seconds": 1
+   "fieldtype": "Section Break"
   },
   {
    "fieldname": "total_qty",
    "fieldtype": "Float",
    "label": "Total Quantity",
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "base_total",
@@ -635,9 +529,7 @@
    "label": "Total (Company Currency)",
    "options": "Company:company:default_currency",
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "base_net_total",
@@ -648,24 +540,18 @@
    "oldfieldtype": "Currency",
    "options": "Company:company:default_currency",
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "column_break_26",
-   "fieldtype": "Column Break",
-   "show_days": 1,
-   "show_seconds": 1
+   "fieldtype": "Column Break"
   },
   {
    "fieldname": "total",
    "fieldtype": "Currency",
    "label": "Total",
    "options": "currency",
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "net_total",
@@ -675,26 +561,20 @@
    "oldfieldtype": "Currency",
    "options": "currency",
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "total_net_weight",
    "fieldtype": "Float",
    "label": "Total Net Weight",
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "taxes_section",
    "fieldtype": "Section Break",
    "oldfieldtype": "Section Break",
-   "options": "fa fa-money",
-   "show_days": 1,
-   "show_seconds": 1
+   "options": "fa fa-money"
   },
   {
    "fieldname": "taxes_and_charges",
@@ -703,30 +583,22 @@
    "oldfieldname": "purchase_other_charges",
    "oldfieldtype": "Link",
    "options": "Purchase Taxes and Charges Template",
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "fieldname": "column_break_50",
-   "fieldtype": "Column Break",
-   "show_days": 1,
-   "show_seconds": 1
+   "fieldtype": "Column Break"
   },
   {
    "fieldname": "shipping_rule",
    "fieldtype": "Link",
    "label": "Shipping Rule",
    "options": "Shipping Rule",
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "fieldname": "section_break_52",
-   "fieldtype": "Section Break",
-   "show_days": 1,
-   "show_seconds": 1
+   "fieldtype": "Section Break"
   },
   {
    "fieldname": "taxes",
@@ -734,17 +606,13 @@
    "label": "Purchase Taxes and Charges",
    "oldfieldname": "purchase_tax_details",
    "oldfieldtype": "Table",
-   "options": "Purchase Taxes and Charges",
-   "show_days": 1,
-   "show_seconds": 1
+   "options": "Purchase Taxes and Charges"
   },
   {
    "collapsible": 1,
    "fieldname": "sec_tax_breakup",
    "fieldtype": "Section Break",
-   "label": "Tax Breakup",
-   "show_days": 1,
-   "show_seconds": 1
+   "label": "Tax Breakup"
   },
   {
    "fieldname": "other_charges_calculation",
@@ -753,17 +621,13 @@
    "no_copy": 1,
    "oldfieldtype": "HTML",
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "totals",
    "fieldtype": "Section Break",
    "oldfieldtype": "Section Break",
-   "options": "fa fa-money",
-   "show_days": 1,
-   "show_seconds": 1
+   "options": "fa fa-money"
   },
   {
    "fieldname": "base_taxes_and_charges_added",
@@ -773,9 +637,7 @@
    "oldfieldtype": "Currency",
    "options": "Company:company:default_currency",
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "base_taxes_and_charges_deducted",
@@ -785,9 +647,7 @@
    "oldfieldtype": "Currency",
    "options": "Company:company:default_currency",
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "base_total_taxes_and_charges",
@@ -798,15 +658,11 @@
    "oldfieldtype": "Currency",
    "options": "Company:company:default_currency",
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "column_break_39",
-   "fieldtype": "Column Break",
-   "show_days": 1,
-   "show_seconds": 1
+   "fieldtype": "Column Break"
   },
   {
    "fieldname": "taxes_and_charges_added",
@@ -816,9 +672,7 @@
    "oldfieldtype": "Currency",
    "options": "currency",
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "taxes_and_charges_deducted",
@@ -828,9 +682,7 @@
    "oldfieldtype": "Currency",
    "options": "currency",
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "total_taxes_and_charges",
@@ -838,18 +690,14 @@
    "label": "Total Taxes and Charges",
    "options": "currency",
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "collapsible": 1,
    "collapsible_depends_on": "discount_amount",
    "fieldname": "discount_section",
    "fieldtype": "Section Break",
-   "label": "Additional Discount",
-   "show_days": 1,
-   "show_seconds": 1
+   "label": "Additional Discount"
   },
   {
    "default": "Grand Total",
@@ -857,9 +705,7 @@
    "fieldtype": "Select",
    "label": "Apply Additional Discount On",
    "options": "\nGrand Total\nNet Total",
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "fieldname": "base_discount_amount",
@@ -867,38 +713,28 @@
    "label": "Additional Discount Amount (Company Currency)",
    "options": "Company:company:default_currency",
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "column_break_45",
-   "fieldtype": "Column Break",
-   "show_days": 1,
-   "show_seconds": 1
+   "fieldtype": "Column Break"
   },
   {
    "fieldname": "additional_discount_percentage",
    "fieldtype": "Float",
    "label": "Additional Discount Percentage",
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "fieldname": "discount_amount",
    "fieldtype": "Currency",
    "label": "Additional Discount Amount",
    "options": "currency",
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "fieldname": "totals_section",
-   "fieldtype": "Section Break",
-   "show_days": 1,
-   "show_seconds": 1
+   "fieldtype": "Section Break"
   },
   {
    "fieldname": "base_grand_total",
@@ -909,9 +745,7 @@
    "oldfieldtype": "Currency",
    "options": "Company:company:default_currency",
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "base_rounding_adjustment",
@@ -920,21 +754,18 @@
    "no_copy": 1,
    "options": "Company:company:default_currency",
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "description": "In Words will be visible once you save the Purchase Order.",
    "fieldname": "base_in_words",
    "fieldtype": "Data",
    "label": "In Words (Company Currency)",
+   "length": 240,
    "oldfieldname": "in_words",
    "oldfieldtype": "Data",
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "base_rounded_total",
@@ -944,16 +775,12 @@
    "oldfieldtype": "Currency",
    "options": "Company:company:default_currency",
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "column_break4",
    "fieldtype": "Column Break",
-   "oldfieldtype": "Column Break",
-   "show_days": 1,
-   "show_seconds": 1
+   "oldfieldtype": "Column Break"
   },
   {
    "fieldname": "grand_total",
@@ -963,9 +790,7 @@
    "oldfieldname": "grand_total_import",
    "oldfieldtype": "Currency",
    "options": "currency",
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "rounding_adjustment",
@@ -974,37 +799,30 @@
    "no_copy": 1,
    "options": "currency",
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "rounded_total",
    "fieldtype": "Currency",
    "label": "Rounded Total",
    "options": "currency",
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "default": "0",
    "fieldname": "disable_rounded_total",
    "fieldtype": "Check",
-   "label": "Disable Rounded Total",
-   "show_days": 1,
-   "show_seconds": 1
+   "label": "Disable Rounded Total"
   },
   {
    "fieldname": "in_words",
    "fieldtype": "Data",
    "label": "In Words",
+   "length": 240,
    "oldfieldname": "in_words_import",
    "oldfieldtype": "Data",
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "advance_paid",
@@ -1013,25 +831,19 @@
    "no_copy": 1,
    "options": "party_account_currency",
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "collapsible": 1,
    "fieldname": "payment_schedule_section",
    "fieldtype": "Section Break",
-   "label": "Payment Terms",
-   "show_days": 1,
-   "show_seconds": 1
+   "label": "Payment Terms"
   },
   {
    "fieldname": "payment_terms_template",
    "fieldtype": "Link",
    "label": "Payment Terms Template",
-   "options": "Payment Terms Template",
-   "show_days": 1,
-   "show_seconds": 1
+   "options": "Payment Terms Template"
   },
   {
    "fieldname": "payment_schedule",
@@ -1039,9 +851,7 @@
    "label": "Payment Schedule",
    "no_copy": 1,
    "options": "Payment Schedule",
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "collapsible": 1,
@@ -1050,9 +860,7 @@
    "fieldtype": "Section Break",
    "label": "Terms and Conditions",
    "oldfieldtype": "Section Break",
-   "options": "fa fa-legal",
-   "show_days": 1,
-   "show_seconds": 1
+   "options": "fa fa-legal"
   },
   {
    "fieldname": "tc_name",
@@ -1061,27 +869,21 @@
    "oldfieldname": "tc_name",
    "oldfieldtype": "Link",
    "options": "Terms and Conditions",
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "fieldname": "terms",
    "fieldtype": "Text Editor",
    "label": "Terms and Conditions",
    "oldfieldname": "terms",
-   "oldfieldtype": "Text Editor",
-   "show_days": 1,
-   "show_seconds": 1
+   "oldfieldtype": "Text Editor"
   },
   {
    "collapsible": 1,
    "fieldname": "more_info",
    "fieldtype": "Section Break",
    "label": "More Information",
-   "oldfieldtype": "Section Break",
-   "show_days": 1,
-   "show_seconds": 1
+   "oldfieldtype": "Section Break"
   },
   {
    "default": "Draft",
@@ -1096,9 +898,7 @@
    "print_hide": 1,
    "read_only": 1,
    "reqd": 1,
-   "search_index": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "search_index": 1
   },
   {
    "fieldname": "ref_sq",
@@ -1109,9 +909,7 @@
    "oldfieldname": "ref_sq",
    "oldfieldtype": "Data",
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "party_account_currency",
@@ -1121,24 +919,18 @@
    "no_copy": 1,
    "options": "Currency",
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "inter_company_order_reference",
    "fieldtype": "Link",
    "label": "Inter Company Order Reference",
    "options": "Sales Order",
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "column_break_74",
-   "fieldtype": "Column Break",
-   "show_days": 1,
-   "show_seconds": 1
+   "fieldtype": "Column Break"
   },
   {
    "depends_on": "eval:!doc.__islocal",
@@ -1148,9 +940,7 @@
    "label": "% Received",
    "no_copy": 1,
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "depends_on": "eval:!doc.__islocal",
@@ -1160,9 +950,7 @@
    "label": "% Billed",
    "no_copy": 1,
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "collapsible": 1,
@@ -1172,8 +960,6 @@
    "oldfieldtype": "Column Break",
    "print_hide": 1,
    "print_width": "50%",
-   "show_days": 1,
-   "show_seconds": 1,
    "width": "50%"
   },
   {
@@ -1184,9 +970,7 @@
    "oldfieldname": "letter_head",
    "oldfieldtype": "Select",
    "options": "Letter Head",
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "allow_on_submit": 1,
@@ -1198,15 +982,11 @@
    "oldfieldtype": "Link",
    "options": "Print Heading",
    "print_hide": 1,
-   "report_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "report_hide": 1
   },
   {
    "fieldname": "column_break_86",
-   "fieldtype": "Column Break",
-   "show_days": 1,
-   "show_seconds": 1
+   "fieldtype": "Column Break"
   },
   {
    "allow_on_submit": 1,
@@ -1214,25 +994,19 @@
    "fieldname": "group_same_items",
    "fieldtype": "Check",
    "label": "Group same items",
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "fieldname": "language",
    "fieldtype": "Data",
    "label": "Print Language",
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "collapsible": 1,
    "fieldname": "subscription_section",
    "fieldtype": "Section Break",
-   "label": "Subscription Section",
-   "show_days": 1,
-   "show_seconds": 1
+   "label": "Subscription Section"
   },
   {
    "allow_on_submit": 1,
@@ -1240,9 +1014,7 @@
    "fieldtype": "Date",
    "label": "From Date",
    "no_copy": 1,
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "allow_on_submit": 1,
@@ -1250,15 +1022,11 @@
    "fieldtype": "Date",
    "label": "To Date",
    "no_copy": 1,
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "fieldname": "column_break_97",
-   "fieldtype": "Column Break",
-   "show_days": 1,
-   "show_seconds": 1
+   "fieldtype": "Column Break"
   },
   {
    "fieldname": "auto_repeat",
@@ -1267,72 +1035,56 @@
    "no_copy": 1,
    "options": "Auto Repeat",
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "allow_on_submit": 1,
    "depends_on": "eval: doc.auto_repeat",
    "fieldname": "update_auto_repeat_reference",
    "fieldtype": "Button",
-   "label": "Update Auto Repeat Reference",
-   "show_days": 1,
-   "show_seconds": 1
+   "label": "Update Auto Repeat Reference"
   },
   {
    "fieldname": "tax_category",
    "fieldtype": "Link",
    "label": "Tax Category",
-   "options": "Tax Category",
-   "show_days": 1,
-   "show_seconds": 1
+   "options": "Tax Category"
   },
   {
    "depends_on": "supplied_items",
    "fieldname": "set_reserve_warehouse",
    "fieldtype": "Link",
    "label": "Set Reserve Warehouse",
-   "options": "Warehouse",
-   "show_days": 1,
-   "show_seconds": 1
+   "options": "Warehouse"
   },
   {
    "collapsible": 1,
    "fieldname": "tracking_section",
    "fieldtype": "Section Break",
-   "label": "Tracking",
-   "show_days": 1,
-   "show_seconds": 1
+   "label": "Tracking"
   },
   {
    "fieldname": "column_break_75",
-   "fieldtype": "Column Break",
-   "show_days": 1,
-   "show_seconds": 1
+   "fieldtype": "Column Break"
   },
   {
    "fieldname": "billing_address",
    "fieldtype": "Link",
    "label": "Select Billing Address",
-   "options": "Address",
-   "show_days": 1,
-   "show_seconds": 1
+   "options": "Address"
   },
   {
    "fieldname": "billing_address_display",
    "fieldtype": "Small Text",
    "label": "Billing Address",
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   }
  ],
  "icon": "fa fa-file-text",
  "idx": 105,
  "is_submittable": 1,
  "links": [],
- "modified": "2020-06-13 22:25:47.333850",
+ "modified": "2020-07-18 05:09:33.800633",
  "modified_by": "Administrator",
  "module": "Buying",
  "name": "Purchase Order",
@@ -1376,12 +1128,6 @@
    "read": 1,
    "role": "Purchase Manager",
    "write": 1
-  },
-  {
-   "email": 1,
-   "print": 1,
-   "read": 1,
-   "role": "Accounts User"
   }
  ],
  "search_fields": "status, transaction_date, supplier,grand_total",
diff --git a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.js b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.js
index 455bd68..4a937f7 100644
--- a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.js
+++ b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.js
@@ -166,7 +166,8 @@
 				{	"fieldtype": "Select", "label": __("Supplier"),
 					"fieldname": "supplier",
 					"options": doc.suppliers.map(d => d.supplier),
-					"reqd": 1 },
+					"reqd": 1,
+					"default": doc.suppliers.length === 1 ? doc.suppliers[0].supplier_name : "" },
 				{	"fieldtype": "Button", "label": __('Create Supplier Quotation'),
 					"fieldname": "make_supplier_quotation", "cssClass": "btn-primary" },
 			]
diff --git a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.json b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.json
index 97aa922..5cd8e6f 100644
--- a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.json
+++ b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.json
@@ -1,4 +1,5 @@
 {
+ "actions": "",
  "allow_import": 1,
  "autoname": "naming_series:",
  "creation": "2016-02-25 01:24:07.224790",
@@ -28,7 +29,6 @@
   "letter_head",
   "more_info",
   "status",
-  "fiscal_year",
   "column_break3",
   "amended_from"
  ],
@@ -219,17 +219,6 @@
    "search_index": 1
   },
   {
-   "fieldname": "fiscal_year",
-   "fieldtype": "Link",
-   "label": "Fiscal Year",
-   "oldfieldname": "fiscal_year",
-   "oldfieldtype": "Select",
-   "options": "Fiscal Year",
-   "print_hide": 1,
-   "reqd": 1,
-   "search_index": 1
-  },
-  {
    "fieldname": "column_break3",
    "fieldtype": "Column Break"
   },
@@ -245,7 +234,8 @@
  ],
  "icon": "fa fa-shopping-cart",
  "is_submittable": 1,
- "modified": "2019-09-24 15:08:32.750661",
+ "links": [],
+ "modified": "2020-06-25 14:37:21.140194",
  "modified_by": "Administrator",
  "module": "Buying",
  "name": "Request for Quotation",
diff --git a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py
index dfdb487..4b85230 100644
--- a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py
+++ b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py
@@ -51,7 +51,7 @@
 
 	def validate_email_id(self, args):
 		if not args.email_id:
-			frappe.throw(_("Row {0}: For supplier {0} Email Address is required to send email").format(args.idx, args.supplier))
+			frappe.throw(_("Row {0}: For Supplier {0}, Email Address is Required to Send Email").format(args.idx, args.supplier))
 
 	def on_submit(self):
 		frappe.db.set(self, 'status', 'Submitted')
@@ -154,7 +154,7 @@
 			sender=sender,attachments = attachments, send_email=True,
 		     	doctype=self.doctype, name=self.name)["name"]
 
-		frappe.msgprint(_("Email sent to supplier {0}").format(data.supplier))
+		frappe.msgprint(_("Email Sent to Supplier {0}").format(data.supplier))
 
 	def get_attachments(self):
 		attachments = [d.name for d in get_attachments(self.doctype, self.name)]
@@ -193,7 +193,7 @@
 def check_portal_enabled(reference_doctype):
 	if not frappe.db.get_value('Portal Menu Item',
 		{'reference_doctype': reference_doctype}, 'enabled'):
-		frappe.throw(_("Request for Quotation is disabled to access from portal, for more check portal settings."))
+		frappe.throw(_("The Access to Request for Quotation From Portal is Disabled. To Allow Access, Enable it in Portal Settings."))
 
 def get_list_context(context=None):
 	from erpnext.controllers.website_list_for_contact import get_list_context
@@ -206,6 +206,7 @@
 	})
 	return list_context
 
+@frappe.whitelist()
 def get_supplier_contacts(doctype, txt, searchfield, start, page_len, filters):
 	return frappe.db.sql("""select `tabContact`.name from `tabContact`, `tabDynamic Link`
 		where `tabDynamic Link`.link_doctype = 'Supplier' and (`tabDynamic Link`.link_name=%(name)s
@@ -259,7 +260,7 @@
 		sq_doc.flags.ignore_permissions = True
 		sq_doc.run_method("set_missing_values")
 		sq_doc.save()
-		frappe.msgprint(_("Supplier Quotation {0} created").format(sq_doc.name))
+		frappe.msgprint(_("Supplier Quotation {0} Created").format(sq_doc.name))
 		return sq_doc.name
 	except Exception:
 		return None
diff --git a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.json b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.json
index 7db1516..660dcff 100644
--- a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.json
+++ b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.json
@@ -593,6 +593,7 @@
    "fieldname": "base_in_words",
    "fieldtype": "Data",
    "label": "In Words (Company Currency)",
+   "length": 240,
    "oldfieldname": "in_words",
    "oldfieldtype": "Data",
    "print_hide": 1,
@@ -642,6 +643,7 @@
    "fieldname": "in_words",
    "fieldtype": "Data",
    "label": "In Words",
+   "length": 240,
    "oldfieldname": "in_words_import",
    "oldfieldtype": "Data",
    "print_hide": 1,
@@ -803,7 +805,7 @@
  "idx": 29,
  "is_submittable": 1,
  "links": [],
- "modified": "2020-05-15 21:24:12.639482",
+ "modified": "2020-07-18 05:10:45.556792",
  "modified_by": "Administrator",
  "module": "Buying",
  "name": "Supplier Quotation",
diff --git a/erpnext/buying/module_onboarding/buying/buying.json b/erpnext/buying/module_onboarding/buying/buying.json
index 6e4bbc9..887f85b 100644
--- a/erpnext/buying/module_onboarding/buying/buying.json
+++ b/erpnext/buying/module_onboarding/buying/buying.json
@@ -19,7 +19,7 @@
  "documentation_url": "https://docs.erpnext.com/docs/user/manual/en/buying",
  "idx": 0,
  "is_complete": 0,
- "modified": "2020-06-01 12:55:09.234944",
+ "modified": "2020-07-08 14:05:28.273641",
  "modified_by": "Administrator",
  "module": "Buying",
  "name": "Buying",
@@ -47,8 +47,7 @@
    "step": "Buying Settings"
   }
  ],
- "subtitle": "Products, Purchases, Analysis and more.",
+ "subtitle": "Products, Purchases, Analysis, and more.",
  "success_message": "The Buying Module is all set up!",
- "title": "Let's Set Up the Buying Module.",
- "user_can_dismiss": 1
+ "title": "Let's Set Up the Buying Module."
 }
\ No newline at end of file
diff --git a/erpnext/buying/number_card/active_suppliers/active_suppliers.json b/erpnext/buying/number_card/active_suppliers/active_suppliers.json
new file mode 100644
index 0000000..91d5b13
--- /dev/null
+++ b/erpnext/buying/number_card/active_suppliers/active_suppliers.json
@@ -0,0 +1,20 @@
+{
+ "creation": "2020-07-20 21:01:02.499689",
+ "docstatus": 0,
+ "doctype": "Number Card",
+ "document_type": "Supplier",
+ "filters_json": "[[\"Supplier\",\"disabled\",\"=\",\"0\"]]",
+ "function": "Count",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "label": "Active Suppliers",
+ "modified": "2020-07-22 12:48:23.295193",
+ "modified_by": "Administrator",
+ "module": "Buying",
+ "name": "Active Suppliers",
+ "owner": "Administrator",
+ "show_percentage_stats": 1,
+ "stats_time_interval": "Monthly",
+ "type": "Document Type"
+}
\ No newline at end of file
diff --git a/erpnext/buying/number_card/annual_purchase/annual_purchase.json b/erpnext/buying/number_card/annual_purchase/annual_purchase.json
new file mode 100644
index 0000000..79f1b65
--- /dev/null
+++ b/erpnext/buying/number_card/annual_purchase/annual_purchase.json
@@ -0,0 +1,22 @@
+{
+ "aggregate_function_based_on": "base_net_total",
+ "creation": "2020-07-20 21:01:02.367127",
+ "docstatus": 0,
+ "doctype": "Number Card",
+ "document_type": "Purchase Order",
+ "dynamic_filters_json": "[[\"Purchase Order\",\"company\",\"=\",\"frappe.defaults.get_user_default(\\\"Company\\\")\"]]",
+ "filters_json": "[[\"Purchase Order\",\"transaction_date\",\"Timespan\",\"this year\",false],[\"Purchase Order\",\"status\",\"not in\",[\"Draft\",\"Cancelled\",\"Closed\",null],false],[\"Purchase Order\",\"docstatus\",\"=\",\"1\",false]]",
+ "function": "Sum",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "label": "Annual Purchase",
+ "modified": "2020-07-22 21:21:58.755188",
+ "modified_by": "Administrator",
+ "module": "Buying",
+ "name": "Annual Purchase",
+ "owner": "Administrator",
+ "show_percentage_stats": 1,
+ "stats_time_interval": "Monthly",
+ "type": "Document Type"
+}
\ No newline at end of file
diff --git a/erpnext/buying/number_card/purchase_orders_to_bill/purchase_orders_to_bill.json b/erpnext/buying/number_card/purchase_orders_to_bill/purchase_orders_to_bill.json
new file mode 100644
index 0000000..44a0456
--- /dev/null
+++ b/erpnext/buying/number_card/purchase_orders_to_bill/purchase_orders_to_bill.json
@@ -0,0 +1,21 @@
+{
+ "creation": "2020-07-20 21:01:02.468514",
+ "docstatus": 0,
+ "doctype": "Number Card",
+ "document_type": "Purchase Order",
+ "dynamic_filters_json": "[[\"Purchase Order\",\"company\",\"=\",\"frappe.defaults.get_user_default(\\\"Company\\\")\"]]",
+ "filters_json": "[[\"Purchase Order\",\"status\",\"in\",[\"To Receive and Bill\",\"To Bill\",null],false],[\"Purchase Order\",\"docstatus\",\"=\",1,false]]",
+ "function": "Count",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "label": "Purchase Orders to Bill",
+ "modified": "2020-07-22 12:48:10.300711",
+ "modified_by": "Administrator",
+ "module": "Buying",
+ "name": "Purchase Orders to Bill",
+ "owner": "Administrator",
+ "show_percentage_stats": 1,
+ "stats_time_interval": "Weekly",
+ "type": "Document Type"
+}
\ No newline at end of file
diff --git a/erpnext/buying/number_card/purchase_orders_to_receive/purchase_orders_to_receive.json b/erpnext/buying/number_card/purchase_orders_to_receive/purchase_orders_to_receive.json
new file mode 100644
index 0000000..442dab4
--- /dev/null
+++ b/erpnext/buying/number_card/purchase_orders_to_receive/purchase_orders_to_receive.json
@@ -0,0 +1,21 @@
+{
+ "creation": "2020-07-20 21:01:02.438012",
+ "docstatus": 0,
+ "doctype": "Number Card",
+ "document_type": "Purchase Order",
+ "dynamic_filters_json": "[[\"Purchase Order\",\"company\",\"=\",\"frappe.defaults.get_user_default(\\\"Company\\\")\"]]",
+ "filters_json": "[[\"Purchase Order\",\"status\",\"in\",[\"To Receive and Bill\",\"To Receive\",null],false],[\"Purchase Order\",\"docstatus\",\"=\",1,false]]",
+ "function": "Count",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "label": "Purchase Orders to Receive",
+ "modified": "2020-07-22 12:47:47.460080",
+ "modified_by": "Administrator",
+ "module": "Buying",
+ "name": "Purchase Orders to Receive",
+ "owner": "Administrator",
+ "show_percentage_stats": 1,
+ "stats_time_interval": "Weekly",
+ "type": "Document Type"
+}
\ No newline at end of file
diff --git a/erpnext/buying/onboarding_step/buying_settings/buying_settings.json b/erpnext/buying/onboarding_step/buying_settings/buying_settings.json
index 6d765af..a788ccd 100644
--- a/erpnext/buying/onboarding_step/buying_settings/buying_settings.json
+++ b/erpnext/buying/onboarding_step/buying_settings/buying_settings.json
@@ -1,19 +1,19 @@
 {
- "action": "Show Form Tour",
+ "action": "Update Settings",
  "creation": "2020-05-06 15:53:44.667414",
  "docstatus": 0,
  "doctype": "Onboarding Step",
  "idx": 0,
  "is_complete": 0,
- "is_mandatory": 1,
- "is_single": 1,
+ "is_mandatory": 0,
+ "is_single": 0,
  "is_skipped": 0,
- "modified": "2020-06-01 12:52:57.668870",
+ "modified": "2020-05-12 18:30:06.323797",
  "modified_by": "Administrator",
  "name": "Buying Settings",
  "owner": "Administrator",
  "reference_document": "Buying Settings",
  "show_full_form": 0,
  "title": "Configure Buying Settings.",
- "validate_action": 0
+ "validate_action": 1
 }
\ No newline at end of file
diff --git a/erpnext/buying/onboarding_step/setup_your_warehouse/setup_your_warehouse.json b/erpnext/buying/onboarding_step/setup_your_warehouse/setup_your_warehouse.json
index 557c905..9457dee 100644
--- a/erpnext/buying/onboarding_step/setup_your_warehouse/setup_your_warehouse.json
+++ b/erpnext/buying/onboarding_step/setup_your_warehouse/setup_your_warehouse.json
@@ -8,13 +8,13 @@
  "is_mandatory": 0,
  "is_single": 0,
  "is_skipped": 0,
- "modified": "2020-05-19 18:54:19.383397",
+ "modified": "2020-07-04 12:33:16.970031",
  "modified_by": "Administrator",
  "name": "Setup your Warehouse",
  "owner": "Administrator",
  "path": "Tree/Warehouse",
  "reference_document": "Warehouse",
  "show_full_form": 0,
- "title": "Setup your Warehouse",
+ "title": "Set up your Warehouse",
  "validate_action": 1
 }
\ No newline at end of file
diff --git a/erpnext/buying/report/procurement_tracker/test_procurement_tracker.py b/erpnext/buying/report/procurement_tracker/test_procurement_tracker.py
index c7204a1..44ab767 100644
--- a/erpnext/buying/report/procurement_tracker/test_procurement_tracker.py
+++ b/erpnext/buying/report/procurement_tracker/test_procurement_tracker.py
@@ -67,4 +67,5 @@
 			"expected_delivery_date": date_obj,
 			"actual_delivery_date": date_obj
 		}
+
 		return expected_data
\ No newline at end of file
diff --git a/erpnext/buying/report/requested_items_to_order/__init__.py b/erpnext/buying/report/requested_items_to_order_and_receive/__init__.py
similarity index 100%
rename from erpnext/buying/report/requested_items_to_order/__init__.py
rename to erpnext/buying/report/requested_items_to_order_and_receive/__init__.py
diff --git a/erpnext/buying/report/requested_items_to_order/requested_items_to_order.js b/erpnext/buying/report/requested_items_to_order_and_receive/requested_items_to_order_and_receive.js
similarity index 95%
rename from erpnext/buying/report/requested_items_to_order/requested_items_to_order.js
rename to erpnext/buying/report/requested_items_to_order_and_receive/requested_items_to_order_and_receive.js
index 9555e82..d727584 100644
--- a/erpnext/buying/report/requested_items_to_order/requested_items_to_order.js
+++ b/erpnext/buying/report/requested_items_to_order_and_receive/requested_items_to_order_and_receive.js
@@ -2,7 +2,7 @@
 // For license information, please see license.txt
 /* eslint-disable */
 
-frappe.query_reports["Requested Items to Order"] = {
+frappe.query_reports["Requested Items to Order and Receive"] = {
 	"filters": [
 		{
 			"fieldname": "company",
diff --git a/erpnext/buying/report/requested_items_to_order/requested_items_to_order.json b/erpnext/buying/report/requested_items_to_order_and_receive/requested_items_to_order_and_receive.json
similarity index 71%
rename from erpnext/buying/report/requested_items_to_order/requested_items_to_order.json
rename to erpnext/buying/report/requested_items_to_order_and_receive/requested_items_to_order_and_receive.json
index 4a0578b..cb158f5 100644
--- a/erpnext/buying/report/requested_items_to_order/requested_items_to_order.json
+++ b/erpnext/buying/report/requested_items_to_order_and_receive/requested_items_to_order_and_receive.json
@@ -1,21 +1,21 @@
 {
  "add_total_row": 1,
- "creation": "2020-05-04 20:23:57.750719",
+ "creation": "2020-07-10 14:28:21.041310",
  "disable_prepared_report": 0,
  "disabled": 0,
  "docstatus": 0,
  "doctype": "Report",
  "idx": 0,
  "is_standard": "Yes",
- "modified": "2020-05-05 13:05:51.723951",
+ "modified": "2020-07-10 14:28:21.041310",
  "modified_by": "Administrator",
  "module": "Buying",
- "name": "Requested Items to Order",
+ "name": "Requested Items to Order and Receive",
  "owner": "Administrator",
  "prepared_report": 0,
  "query": "",
  "ref_doctype": "Material Request",
- "report_name": "Requested Items to Order",
+ "report_name": "Requested Items to Order and Receive",
  "report_type": "Script Report",
  "roles": [
   {
diff --git a/erpnext/buying/report/requested_items_to_order/requested_items_to_order.py b/erpnext/buying/report/requested_items_to_order_and_receive/requested_items_to_order_and_receive.py
similarity index 80%
rename from erpnext/buying/report/requested_items_to_order/requested_items_to_order.py
rename to erpnext/buying/report/requested_items_to_order_and_receive/requested_items_to_order_and_receive.py
index cca01b1..faf67c9 100644
--- a/erpnext/buying/report/requested_items_to_order/requested_items_to_order.py
+++ b/erpnext/buying/report/requested_items_to_order_and_receive/requested_items_to_order_and_receive.py
@@ -59,8 +59,11 @@
 			sum(ifnull(mr_item.stock_qty, 0)) as qty,
 			ifnull(mr_item.stock_uom, '') as uom,
 			sum(ifnull(mr_item.ordered_qty, 0)) as ordered_qty,
-			(sum(mr_item.stock_qty) - sum(ifnull(mr_item.ordered_qty, 0))) as qty_to_order,
+			sum(ifnull(mr_item.received_qty, 0)) as received_qty,
+			(sum(ifnull(mr_item.stock_qty, 0)) - sum(ifnull(mr_item.received_qty, 0))) as qty_to_receive,
+			(sum(ifnull(mr_item.stock_qty, 0)) - sum(ifnull(mr_item.ordered_qty, 0))) as qty_to_order,
 			mr_item.item_name as item_name,
+			mr_item.description as "description",
 			mr.company as company
 		from
 			`tabMaterial Request` mr, `tabMaterial Request Item` mr_item
@@ -78,7 +81,7 @@
 	return data
 
 def update_qty_columns(row_to_update, data_row):
-	fields = ["qty", "ordered_qty", "qty_to_order"]
+	fields = ["qty", "ordered_qty", "received_qty", "qty_to_receive", "qty_to_order"]
 	for field in fields:
 		row_to_update[field] += flt(data_row[field])
 
@@ -92,7 +95,9 @@
 			item_qty_map[row["item_code"]] = {
 				"qty" : row["qty"],
 				"ordered_qty" : row["ordered_qty"],
-				"qty_to_order" : row["qty_to_order"]
+				"received_qty": row["received_qty"],
+				"qty_to_receive": row["qty_to_receive"],
+				"qty_to_order" : row["qty_to_order"],
 			}
 		else:
 			item_entry = item_qty_map[row["item_code"]]
@@ -122,7 +127,7 @@
 	return data, chart_data
 
 def prepare_chart_data(item_data):
-	labels, qty_to_order, ordered_qty = [], [], []
+	labels, qty_to_order, ordered_qty, received_qty, qty_to_receive = [], [], [], [], []
 
 	if len(item_data) > 30:
 		item_data = dict(list(item_data.items())[:30])
@@ -132,6 +137,8 @@
 		labels.append(row)
 		qty_to_order.append(mr_row["qty_to_order"])
 		ordered_qty.append(mr_row["ordered_qty"])
+		received_qty.append(mr_row["received_qty"])
+		qty_to_receive.append(mr_row["qty_to_receive"])
 
 	chart_data = {
 		"data" : {
@@ -144,6 +151,14 @@
 				{
 					'name': _('Ordered Qty'),
 					'values': ordered_qty
+				},
+				{
+					'name': _('Received Qty'),
+					'values': received_qty
+				},
+				{
+					'name': _('Qty to Receive'),
+					'values': qty_to_receive
 				}
 			]
 		},
@@ -193,7 +208,13 @@
 			"width": 100
 		},
 		{
-			"label": _("UOM"),
+			"label": _("Description"),
+			"fieldname": "description",
+			"fieldtype": "Data",
+			"width": 200
+		},
+		{
+			"label": _("Stock UOM"),
 			"fieldname": "uom",
 			"fieldtype": "Data",
 			"width": 100,
@@ -201,7 +222,7 @@
 
 	columns.extend([
 		{
-			"label": _("Qty"),
+			"label": _("Stock Qty"),
 			"fieldname": "qty",
 			"fieldtype": "Float",
 			"width": 120,
@@ -215,6 +236,20 @@
 			"convertible": "qty"
 		},
 		{
+			"label": _("Received Qty"),
+			"fieldname": "received_qty",
+			"fieldtype": "Float",
+			"width": 120,
+			"convertible": "qty"
+		},
+		{
+			"label": _("Qty to Receive"),
+			"fieldname": "qty_to_receive",
+			"fieldtype": "Float",
+			"width": 120,
+			"convertible": "qty"
+		},
+		{
 			"label": _("Qty to Order"),
 			"fieldname": "qty_to_order",
 			"fieldtype": "Float",
diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py
index f54b593..89c38c7 100644
--- a/erpnext/controllers/accounts_controller.py
+++ b/erpnext/controllers/accounts_controller.py
@@ -20,6 +20,7 @@
 from six import text_type
 from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_accounting_dimensions
 from erpnext.stock.get_item_details import get_item_warehouse
+from erpnext.stock.doctype.packed_item.packed_item import make_packing_list
 
 force_item_fields = ("item_group", "brand", "stock_uom", "is_fixed_asset", "item_tax_rate", "pricing_rules")
 
@@ -1013,6 +1014,7 @@
 def get_advance_payment_entries(party_type, party, party_account, order_doctype,
 		order_list=None, include_unallocated=True, against_all_orders=False, limit=None):
 	party_account_field = "paid_from" if party_type == "Customer" else "paid_to"
+	currency_field = "paid_from_account_currency" if party_type == "Customer" else "paid_to_account_currency"
 	payment_type = "Receive" if party_type == "Customer" else "Pay"
 	payment_entries_against_order, unallocated_payment_entries = [], []
 	limit_cond = "limit %s" % limit if limit else ""
@@ -1029,14 +1031,15 @@
 			select
 				"Payment Entry" as reference_type, t1.name as reference_name,
 				t1.remarks, t2.allocated_amount as amount, t2.name as reference_row,
-				t2.reference_name as against_order, t1.posting_date
+				t2.reference_name as against_order, t1.posting_date,
+				t1.{0} as currency
 			from `tabPayment Entry` t1, `tabPayment Entry Reference` t2
 			where
-				t1.name = t2.parent and t1.{0} = %s and t1.payment_type = %s
+				t1.name = t2.parent and t1.{1} = %s and t1.payment_type = %s
 				and t1.party_type = %s and t1.party = %s and t1.docstatus = 1
-				and t2.reference_doctype = %s {1}
-			order by t1.posting_date {2}
-		""".format(party_account_field, reference_condition, limit_cond),
+				and t2.reference_doctype = %s {2}
+			order by t1.posting_date {3}
+		""".format(currency_field, party_account_field, reference_condition, limit_cond),
 													  [party_account, payment_type, party_type, party,
 													   order_doctype] + order_list, as_dict=1)
 
@@ -1301,6 +1304,7 @@
 	parent.set_qty_as_per_stock_uom()
 	parent.calculate_taxes_and_totals()
 	if parent_doctype == "Sales Order":
+		make_packing_list(parent)
 		parent.set_gross_profit()
 	frappe.get_doc('Authorization Control').validate_approving_authority(parent.doctype,
 		parent.company, parent.base_grand_total)
diff --git a/erpnext/controllers/queries.py b/erpnext/controllers/queries.py
index f6a8d27..31e3498 100644
--- a/erpnext/controllers/queries.py
+++ b/erpnext/controllers/queries.py
@@ -10,7 +10,8 @@
 from erpnext.stock.get_item_details import _get_item_tax_template
 from frappe.utils import unique
 
- # searches for active employees
+# searches for active employees
+@frappe.whitelist()
 def employee_query(doctype, txt, searchfield, start, page_len, filters):
 	conditions = []
 	fields = get_fields("Employee", ["name", "employee_name"])
@@ -40,6 +41,7 @@
 
 
 # searches for leads which are not converted
+@frappe.whitelist()
 def lead_query(doctype, txt, searchfield, start, page_len, filters):
 	fields = get_fields("Lead", ["name", "lead_name", "company_name"])
 
@@ -69,6 +71,7 @@
 
 
  # searches for customer
+@frappe.whitelist()
 def customer_query(doctype, txt, searchfield, start, page_len, filters):
 	conditions = []
 	cust_master_name = frappe.defaults.get_user_default("cust_master_name")
@@ -106,6 +109,7 @@
 
 
 # searches for supplier
+@frappe.whitelist()
 def supplier_query(doctype, txt, searchfield, start, page_len, filters):
 	supp_master_name = frappe.defaults.get_user_default("supp_master_name")
 	if supp_master_name == "Supplier Name":
@@ -137,6 +141,7 @@
 		})
 
 
+@frappe.whitelist()
 def tax_account_query(doctype, txt, searchfield, start, page_len, filters):
 	company_currency = erpnext.get_company_currency(filters.get('company'))
 
@@ -162,6 +167,7 @@
 	return tax_accounts
 
 
+@frappe.whitelist()
 def item_query(doctype, txt, searchfield, start, page_len, filters, as_dict=False):
 	conditions = []
 
@@ -224,6 +230,7 @@
 			}, as_dict=as_dict)
 
 
+@frappe.whitelist()
 def bom(doctype, txt, searchfield, start, page_len, filters):
 	conditions = []
 	fields = get_fields("BOM", ["name", "item"])
@@ -250,6 +257,7 @@
 		})
 
 
+@frappe.whitelist()
 def get_project_name(doctype, txt, searchfield, start, page_len, filters):
 	cond = ''
 	if filters.get('customer'):
@@ -276,6 +284,7 @@
 			})
 
 
+@frappe.whitelist()
 def get_delivery_notes_to_be_billed(doctype, txt, searchfield, start, page_len, filters, as_dict):
 	fields = get_fields("Delivery Note", ["name", "customer", "posting_date"])
 
@@ -305,6 +314,7 @@
 	}, {"txt": ("%%%s%%" % txt)}, as_dict=as_dict)
 
 
+@frappe.whitelist()
 def get_batch_no(doctype, txt, searchfield, start, page_len, filters):
 	cond = ""
 	if filters.get("posting_date"):
@@ -362,6 +372,7 @@
 			limit %(start)s, %(page_len)s""".format(cond, match_conditions=get_match_cond(doctype)), args)
 
 
+@frappe.whitelist()
 def get_account_list(doctype, txt, searchfield, start, page_len, filters):
 	filter_list = []
 
@@ -385,6 +396,7 @@
 		limit_start=start, limit_page_length=page_len, as_list=True)
 
 
+@frappe.whitelist()
 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
@@ -570,7 +582,8 @@
 		args = {
 			'item_code': filters.get('item_code'),
 			'posting_date': filters.get('valid_from'),
-			'tax_category': filters.get('tax_category')
+			'tax_category': filters.get('tax_category'),
+			'company': filters.get('company')
 		}
 
 		taxes = _get_item_tax_template(args, taxes, for_validate=True)
diff --git a/erpnext/controllers/sales_and_purchase_return.py b/erpnext/controllers/sales_and_purchase_return.py
index 90c67f1..3f127a2 100644
--- a/erpnext/controllers/sales_and_purchase_return.py
+++ b/erpnext/controllers/sales_and_purchase_return.py
@@ -213,7 +213,7 @@
 		doc.return_against = source.name
 		doc.ignore_pricing_rule = 1
 		doc.set_warehouse = ""
-		if doctype == "Sales Invoice":
+		if doctype == "Sales Invoice" or doctype == "POS Invoice":
 			doc.is_pos = source.is_pos
 
 			# look for Print Heading "Credit Note"
@@ -229,7 +229,7 @@
 				tax.tax_amount = -1 * tax.tax_amount
 
 		if doc.get("is_return"):
-			if doc.doctype == 'Sales Invoice':
+			if doc.doctype == 'Sales Invoice' or doc.doctype == 'POS Invoice':
 				doc.set('payments', [])
 				for data in source.payments:
 					paid_amount = 0.00
@@ -241,8 +241,11 @@
 						'mode_of_payment': data.mode_of_payment,
 						'type': data.type,
 						'amount': -1 * paid_amount,
-						'base_amount': -1 * base_paid_amount
+						'base_amount': -1 * base_paid_amount,
+						'account': data.account
 					})
+				if doc.is_pos:
+					doc.paid_amount = -1 * source.paid_amount
 			elif doc.doctype == 'Purchase Invoice':
 				doc.paid_amount = -1 * source.paid_amount
 				doc.base_paid_amount = -1 * source.base_paid_amount
@@ -287,7 +290,7 @@
 			target_doc.dn_detail = source_doc.name
 			if default_warehouse_for_sales_return:
 				target_doc.warehouse = default_warehouse_for_sales_return
-		elif doctype == "Sales Invoice":
+		elif doctype == "Sales Invoice" or doctype == "POS Invoice":
 			target_doc.sales_order = source_doc.sales_order
 			target_doc.delivery_note = source_doc.delivery_note
 			target_doc.so_detail = source_doc.so_detail
diff --git a/erpnext/controllers/status_updater.py b/erpnext/controllers/status_updater.py
index b465a10..0dc9878 100644
--- a/erpnext/controllers/status_updater.py
+++ b/erpnext/controllers/status_updater.py
@@ -85,6 +85,12 @@
 	"Bank Transaction": [
 		["Unreconciled", "eval:self.docstatus == 1 and self.unallocated_amount>0"],
 		["Reconciled", "eval:self.docstatus == 1 and self.unallocated_amount<=0"]
+	],
+	"POS Opening Entry": [
+		["Draft", None],
+		["Open", "eval:self.docstatus == 1 and not self.pos_closing_entry"],
+		["Closed", "eval:self.docstatus == 1 and self.pos_closing_entry"],
+		["Cancelled", "eval:self.docstatus == 2"],
 	]
 }
 
diff --git a/erpnext/controllers/stock_controller.py b/erpnext/controllers/stock_controller.py
index 759c6cd..e8483da 100644
--- a/erpnext/controllers/stock_controller.py
+++ b/erpnext/controllers/stock_controller.py
@@ -96,6 +96,7 @@
 							"account": warehouse_account[sle.warehouse]["account"],
 							"against": item_row.expense_account,
 							"cost_center": item_row.cost_center,
+							"project": item_row.project or self.get('project'),
 							"remarks": self.get("remarks") or "Accounting Entry for Stock",
 							"debit": flt(sle.stock_value_difference, precision),
 							"is_opening": item_row.get("is_opening") or self.get("is_opening") or "No",
@@ -106,6 +107,7 @@
 							"account": item_row.expense_account,
 							"against": warehouse_account[sle.warehouse]["account"],
 							"cost_center": item_row.cost_center,
+							"project": item_row.project or self.get('project'),
 							"remarks": self.get("remarks") or "Accounting Entry for Stock",
 							"credit": flt(sle.stock_value_difference, precision),
 							"project": item_row.get("project") or self.get("project"),
diff --git a/erpnext/controllers/taxes_and_totals.py b/erpnext/controllers/taxes_and_totals.py
index 4e568e2..572e1ca 100644
--- a/erpnext/controllers/taxes_and_totals.py
+++ b/erpnext/controllers/taxes_and_totals.py
@@ -53,7 +53,8 @@
 					'tax_category': self.doc.get('tax_category'),
 					'posting_date': self.doc.get('posting_date'),
 					'bill_date': self.doc.get('bill_date'),
-					'transaction_date': self.doc.get('transaction_date')
+					'transaction_date': self.doc.get('transaction_date'),
+					'company': self.doc.get('company')
 				}
 
 				item_group = item_doc.item_group
@@ -369,7 +370,7 @@
 
 		self._set_in_company_currency(self.doc, ["total_taxes_and_charges", "rounding_adjustment"])
 
-		if self.doc.doctype in ["Quotation", "Sales Order", "Delivery Note", "Sales Invoice"]:
+		if self.doc.doctype in ["Quotation", "Sales Order", "Delivery Note", "Sales Invoice", "POS Invoice"]:
 			self.doc.base_grand_total = flt(self.doc.grand_total * self.doc.conversion_rate, self.doc.precision("base_grand_total")) \
 				if self.doc.total_taxes_and_charges else self.doc.base_net_total
 		else:
@@ -596,7 +597,7 @@
 		base_rate_with_margin = 0.0
 		if item.price_list_rate:
 			if item.pricing_rules and not self.doc.ignore_pricing_rule:
-				for d in item.pricing_rules.split(','):
+				for d in json.loads(item.pricing_rules):
 					pricing_rule = frappe.get_cached_doc('Pricing Rule', d)
 
 					if (pricing_rule.margin_type == 'Amount' and pricing_rule.currency == self.doc.currency)\
@@ -618,17 +619,14 @@
 		self.doc.other_charges_calculation = get_itemised_tax_breakup_html(self.doc)
 
 	def update_paid_amount_for_return(self, total_amount_to_pay):
-		default_mode_of_payment = frappe.db.get_value('Sales Invoice Payment',
-			{'parent': self.doc.pos_profile, 'default': 1},
-			['mode_of_payment', 'type', 'account'], as_dict=1)
+		default_mode_of_payment = frappe.db.get_value('POS Payment Method',
+			{'parent': self.doc.pos_profile, 'default': 1}, ['mode_of_payment'], as_dict=1)
 
 		self.doc.payments = []
 
 		if default_mode_of_payment:
 			self.doc.append('payments', {
 				'mode_of_payment': default_mode_of_payment.mode_of_payment,
-				'type': default_mode_of_payment.type,
-				'account': default_mode_of_payment.account,
 				'amount': total_amount_to_pay
 			})
 		else:
diff --git a/erpnext/controllers/tests/test_mapper.py b/erpnext/controllers/tests/test_mapper.py
index 8839e00..66459fd 100644
--- a/erpnext/controllers/tests/test_mapper.py
+++ b/erpnext/controllers/tests/test_mapper.py
@@ -13,14 +13,12 @@
 		'''Test mapping of multiple source docs on a single target doc'''
 
 		make_test_records("Item")
-		items = frappe.get_all("Item", fields = ["name", "item_code"], filters = {'is_sales_item': 1, 'has_variants': 0, 'disabled': 0})
-		customers = frappe.get_all("Customer")
-		if items and customers:
-			# Make source docs (quotations) and a target doc (sales order)
-			customer = random.choice(customers).name
-			qtn1, item_list_1 = self.make_quotation(items, customer)
-			qtn2, item_list_2 = self.make_quotation(items, customer)
-			so, item_list_3 = self.make_sales_order()
+		items = ['_Test Item', '_Test Item 2', '_Test FG Item']
+
+		# Make source docs (quotations) and a target doc (sales order)
+		qtn1, item_list_1 = self.make_quotation(items, '_Test Customer')
+		qtn2, item_list_2 = self.make_quotation(items, '_Test Customer')
+		so, item_list_3 = self.make_sales_order()
 
 		# Map source docs to target with corresponding mapper method
 		method = "erpnext.selling.doctype.quotation.quotation.make_sales_order"
@@ -28,18 +26,12 @@
 
 		# Assert that all inserted items are present in updated sales order
 		src_items = item_list_1 + item_list_2 + item_list_3
-		self.assertEqual(set([d.item_code for d in src_items]),
+		self.assertEqual(set([d for d in src_items]),
 			set([d.item_code for d in updated_so.items]))
 
-	def get_random_items(self, items, limit):
-		'''Get a number of random items from a list of given items'''
-		random_items = []
-		for i in range(0, limit):
-			random_items.append(random.choice(items))
-		return random_items
 
-	def make_quotation(self, items, customer):
-		item_list = self.get_random_items(items, 3)
+	def make_quotation(self, item_list, customer):
+
 		qtn = frappe.get_doc({
 			"doctype": "Quotation",
 			"quotation_to": "Customer",
@@ -49,7 +41,7 @@
 			"valid_till" : add_months(nowdate(), 1)
 		})
 		for item in item_list:
-			qtn.append("items", {"qty": "2", "item_code": item.item_code})
+			qtn.append("items", {"qty": "2", "item_code": item})
 
 		qtn.submit()
 		return qtn, item_list
@@ -60,7 +52,7 @@
 			"base_rate": 100.0,
 			"description": "CPU",
 			"doctype": "Sales Order Item",
-			"item_code": "_Test Item Home Desktop 100",
+			"item_code": "_Test Item",
 			"item_name": "CPU",
 			"parentfield": "items",
 			"qty": 10.0,
@@ -72,4 +64,4 @@
 		})
 		so = frappe.get_doc(frappe.get_test_records('Sales Order')[0])
 		so.insert(ignore_permissions=True)
-		return so, [item]
+		return so, [item.item_code]
diff --git a/erpnext/controllers/tests/test_qty_based_taxes.py b/erpnext/controllers/tests/test_qty_based_taxes.py
index fd9936b..aaeac5d 100644
--- a/erpnext/controllers/tests/test_qty_based_taxes.py
+++ b/erpnext/controllers/tests/test_qty_based_taxes.py
@@ -30,6 +30,7 @@
         self.item_tax_template = frappe.get_doc({
             'doctype': 'Item Tax Template',
             'title': uuid4(),
+            'company': self.company.name,
             'taxes': [
                 {
                     'tax_type': self.account.name,
diff --git a/erpnext/controllers/trends.py b/erpnext/controllers/trends.py
index 092baa4..9b4b0eb 100644
--- a/erpnext/controllers/trends.py
+++ b/erpnext/controllers/trends.py
@@ -33,7 +33,7 @@
 			frappe.throw(_("{0} is mandatory").format(f))
 
 	if not frappe.db.exists("Fiscal Year", filters.get("fiscal_year")):
-		frappe.throw(_("Fiscal Year: {0} does not exists").format(filters.get("fiscal_year")))
+		frappe.throw(_("Fiscal Year {0} Does Not Exist").format(filters.get("fiscal_year")))
 
 	if filters.get("based_on") == filters.get("group_by"):
 		frappe.throw(_("'Based On' and 'Group By' can not be same"))
diff --git a/erpnext/crm/crm_dashboard/crm/crm.json b/erpnext/crm/crm_dashboard/crm/crm.json
new file mode 100644
index 0000000..69c2c8a
--- /dev/null
+++ b/erpnext/crm/crm_dashboard/crm/crm.json
@@ -0,0 +1,58 @@
+{
+ "cards": [
+  {
+   "card": "New Lead (Last 1 Month)"
+  },
+  {
+   "card": "New Opportunity (Last 1 Month)"
+  },
+  {
+   "card": "Won Opportunity (Last 1 Month)"
+  },
+  {
+   "card": "Open Opportunity"
+  }
+ ],
+ "charts": [
+  {
+   "chart": "Incoming Leads",
+   "width": "Full"
+  },
+  {
+   "chart": "Opportunity Trends",
+   "width": "Full"
+  },
+  {
+   "chart": "Won Opportunities",
+   "width": "Full"
+  },
+  {
+   "chart": "Territory Wise Opportunity Count",
+   "width": "Half"
+  },
+  {
+   "chart": "Opportunities via Campaigns",
+   "width": "Half"
+  },
+  {
+   "chart": "Territory Wise Sales",
+   "width": "Full"
+  },
+  {
+   "chart": "Lead Source",
+   "width": "Half"
+  }
+ ],
+ "creation": "2020-07-20 20:17:15.985657",
+ "dashboard_name": "CRM",
+ "docstatus": 0,
+ "doctype": "Dashboard",
+ "idx": 0,
+ "is_default": 0,
+ "is_standard": 1,
+ "modified": "2020-07-21 18:56:47.230053",
+ "modified_by": "Administrator",
+ "module": "CRM",
+ "name": "CRM",
+ "owner": "Administrator"
+}
\ No newline at end of file
diff --git a/erpnext/crm/dashboard_chart/incoming_leads/incoming_leads.json b/erpnext/crm/dashboard_chart/incoming_leads/incoming_leads.json
new file mode 100644
index 0000000..82398eb
--- /dev/null
+++ b/erpnext/crm/dashboard_chart/incoming_leads/incoming_leads.json
@@ -0,0 +1,28 @@
+{
+ "based_on": "creation",
+ "chart_name": "Incoming Leads",
+ "chart_type": "Count",
+ "creation": "2020-07-20 20:17:15.639164",
+ "custom_options": "{\"type\": \"line\", \"axisOptions\": {\"shortenYAxisNumbers\": 1}, \"tooltipOptions\": {}, \"lineOptions\": {\"regionFill\": 1}}",
+ "docstatus": 0,
+ "doctype": "Dashboard Chart",
+ "document_type": "Lead",
+ "dynamic_filters_json": "[[\"Lead\",\"company\",\"=\",\"frappe.defaults.get_user_default(\\\"Company\\\")\"]]",
+ "filters_json": "[]",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "last_synced_on": "2020-07-22 15:49:19.896501",
+ "modified": "2020-07-22 16:06:34.941729",
+ "modified_by": "Administrator",
+ "module": "CRM",
+ "name": "Incoming Leads",
+ "number_of_groups": 0,
+ "owner": "Administrator",
+ "time_interval": "Weekly",
+ "timeseries": 1,
+ "timespan": "Last Quarter",
+ "type": "Bar",
+ "use_report_chart": 0,
+ "y_axis": []
+}
\ No newline at end of file
diff --git a/erpnext/crm/dashboard_chart/lead_source/lead_source.json b/erpnext/crm/dashboard_chart/lead_source/lead_source.json
new file mode 100644
index 0000000..f25fea5
--- /dev/null
+++ b/erpnext/crm/dashboard_chart/lead_source/lead_source.json
@@ -0,0 +1,27 @@
+{
+ "chart_name": "Lead Source",
+ "chart_type": "Group By",
+ "creation": "2020-07-20 20:17:15.842106",
+ "custom_options": "{\"truncateLegends\": 1, \"maxSlices\": 8}",
+ "docstatus": 0,
+ "doctype": "Dashboard Chart",
+ "document_type": "Lead",
+ "dynamic_filters_json": "[[\"Lead\",\"company\",\"=\",\"frappe.defaults.get_user_default(\\\"Company\\\")\"]]",
+ "filters_json": "[]",
+ "group_by_based_on": "source",
+ "group_by_type": "Count",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "last_synced_on": "2020-07-22 16:11:14.170636",
+ "modified": "2020-07-22 16:13:38.696710",
+ "modified_by": "Administrator",
+ "module": "CRM",
+ "name": "Lead Source",
+ "number_of_groups": 0,
+ "owner": "Administrator",
+ "timeseries": 0,
+ "type": "Donut",
+ "use_report_chart": 0,
+ "y_axis": []
+}
\ No newline at end of file
diff --git a/erpnext/crm/dashboard_chart/opportunities_via_campaigns/opportunities_via_campaigns.json b/erpnext/crm/dashboard_chart/opportunities_via_campaigns/opportunities_via_campaigns.json
new file mode 100644
index 0000000..4adda9a
--- /dev/null
+++ b/erpnext/crm/dashboard_chart/opportunities_via_campaigns/opportunities_via_campaigns.json
@@ -0,0 +1,27 @@
+{
+ "chart_name": "Opportunities via Campaigns",
+ "chart_type": "Group By",
+ "creation": "2020-07-20 20:17:15.705402",
+ "custom_options": "{\"truncateLegends\": 1, \"maxSlices\": 8}",
+ "docstatus": 0,
+ "doctype": "Dashboard Chart",
+ "document_type": "Opportunity",
+ "dynamic_filters_json": "[[\"Opportunity\",\"company\",\"=\",\"frappe.defaults.get_user_default(\\\"Company\\\")\"]]",
+ "filters_json": "[]",
+ "group_by_based_on": "campaign",
+ "group_by_type": "Count",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "last_synced_on": "2020-07-22 15:45:32.572011",
+ "modified": "2020-07-22 16:10:02.497726",
+ "modified_by": "Administrator",
+ "module": "CRM",
+ "name": "Opportunities via Campaigns",
+ "number_of_groups": 0,
+ "owner": "Administrator",
+ "timeseries": 0,
+ "type": "Pie",
+ "use_report_chart": 0,
+ "y_axis": []
+}
\ No newline at end of file
diff --git a/erpnext/crm/dashboard_chart/opportunity_trends/opportunity_trends.json b/erpnext/crm/dashboard_chart/opportunity_trends/opportunity_trends.json
new file mode 100644
index 0000000..08e26cd
--- /dev/null
+++ b/erpnext/crm/dashboard_chart/opportunity_trends/opportunity_trends.json
@@ -0,0 +1,28 @@
+{
+ "based_on": "creation",
+ "chart_name": "Opportunity Trends",
+ "chart_type": "Count",
+ "creation": "2020-07-20 20:17:15.672124",
+ "custom_options": "",
+ "docstatus": 0,
+ "doctype": "Dashboard Chart",
+ "document_type": "Opportunity",
+ "dynamic_filters_json": "[[\"Opportunity\",\"company\",\"=\",\"frappe.defaults.get_user_default(\\\"Company\\\")\"]]",
+ "filters_json": "[]",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "last_synced_on": "2020-07-22 15:45:32.590967",
+ "modified": "2020-07-22 16:08:33.100532",
+ "modified_by": "Administrator",
+ "module": "CRM",
+ "name": "Opportunity Trends",
+ "number_of_groups": 0,
+ "owner": "Administrator",
+ "time_interval": "Weekly",
+ "timeseries": 1,
+ "timespan": "Last Quarter",
+ "type": "Bar",
+ "use_report_chart": 0,
+ "y_axis": []
+}
\ No newline at end of file
diff --git a/erpnext/crm/dashboard_chart/territory_wise_opportunity_count/territory_wise_opportunity_count.json b/erpnext/crm/dashboard_chart/territory_wise_opportunity_count/territory_wise_opportunity_count.json
new file mode 100644
index 0000000..8b15ec9
--- /dev/null
+++ b/erpnext/crm/dashboard_chart/territory_wise_opportunity_count/territory_wise_opportunity_count.json
@@ -0,0 +1,27 @@
+{
+ "chart_name": "Territory Wise Opportunity Count",
+ "chart_type": "Group By",
+ "creation": "2020-07-20 20:17:15.774176",
+ "custom_options": "{\"truncateLegends\": 1, \"maxSlices\": 8}",
+ "docstatus": 0,
+ "doctype": "Dashboard Chart",
+ "document_type": "Opportunity",
+ "dynamic_filters_json": "[[\"Opportunity\",\"company\",\"=\",\"frappe.defaults.get_user_default(\\\"Company\\\")\"]]",
+ "filters_json": "[]",
+ "group_by_based_on": "territory",
+ "group_by_type": "Count",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "last_synced_on": "2020-07-22 15:45:32.134026",
+ "modified": "2020-07-22 16:09:42.921547",
+ "modified_by": "Administrator",
+ "module": "CRM",
+ "name": "Territory Wise Opportunity Count",
+ "number_of_groups": 0,
+ "owner": "Administrator",
+ "timeseries": 0,
+ "type": "Donut",
+ "use_report_chart": 0,
+ "y_axis": []
+}
\ No newline at end of file
diff --git a/erpnext/crm/dashboard_chart/territory_wise_sales/territory_wise_sales.json b/erpnext/crm/dashboard_chart/territory_wise_sales/territory_wise_sales.json
new file mode 100644
index 0000000..fe142b4
--- /dev/null
+++ b/erpnext/crm/dashboard_chart/territory_wise_sales/territory_wise_sales.json
@@ -0,0 +1,28 @@
+{
+ "aggregate_function_based_on": "opportunity_amount",
+ "chart_name": "Territory Wise Sales",
+ "chart_type": "Group By",
+ "creation": "2020-07-20 20:17:15.809008",
+ "custom_options": "",
+ "docstatus": 0,
+ "doctype": "Dashboard Chart",
+ "document_type": "Opportunity",
+ "dynamic_filters_json": "[[\"Opportunity\",\"company\",\"=\",\"frappe.defaults.get_user_default(\\\"Company\\\")\"]]",
+ "filters_json": "[[\"Opportunity\",\"status\",\"=\",\"Converted\",false]]",
+ "group_by_based_on": "territory",
+ "group_by_type": "Sum",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "last_synced_on": "2020-07-22 15:45:32.501313",
+ "modified": "2020-07-22 16:10:28.308110",
+ "modified_by": "Administrator",
+ "module": "CRM",
+ "name": "Territory Wise Sales",
+ "number_of_groups": 0,
+ "owner": "Administrator",
+ "timeseries": 0,
+ "type": "Bar",
+ "use_report_chart": 0,
+ "y_axis": []
+}
\ No newline at end of file
diff --git a/erpnext/crm/dashboard_chart/won_opportunities/won_opportunities.json b/erpnext/crm/dashboard_chart/won_opportunities/won_opportunities.json
new file mode 100644
index 0000000..2b5576b
--- /dev/null
+++ b/erpnext/crm/dashboard_chart/won_opportunities/won_opportunities.json
@@ -0,0 +1,27 @@
+{
+ "based_on": "modified",
+ "chart_name": "Won Opportunities",
+ "chart_type": "Count",
+ "creation": "2020-07-20 20:17:15.738889",
+ "docstatus": 0,
+ "doctype": "Dashboard Chart",
+ "document_type": "Opportunity",
+ "dynamic_filters_json": "[[\"Opportunity\",\"company\",\"=\",\"frappe.defaults.get_user_default(\\\"Company\\\")\"]]",
+ "filters_json": "[[\"Opportunity\",\"status\",\"=\",\"Converted\",false]]",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "last_synced_on": "2020-07-22 15:45:32.575964",
+ "modified": "2020-07-22 16:09:14.265231",
+ "modified_by": "Administrator",
+ "module": "CRM",
+ "name": "Won Opportunities",
+ "number_of_groups": 0,
+ "owner": "Administrator",
+ "time_interval": "Monthly",
+ "timeseries": 1,
+ "timespan": "Last Year",
+ "type": "Bar",
+ "use_report_chart": 0,
+ "y_axis": []
+}
\ No newline at end of file
diff --git a/erpnext/crm/dashboard_fixtures.py b/erpnext/crm/dashboard_fixtures.py
deleted file mode 100644
index 0535cbb..0000000
--- a/erpnext/crm/dashboard_fixtures.py
+++ /dev/null
@@ -1,214 +0,0 @@
-# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-import frappe, erpnext, json
-from frappe import _
-
-def get_data():
-	return frappe._dict({
-        "dashboards": get_dashboards(),
-        "charts": get_charts(),
-        "number_cards": get_number_cards()
-	})
-
-def get_dashboards():
-	return [{
-            "doctype": "Dashboard",
-            "name": "CRM",
-            "dashboard_name": "CRM",
-            "charts": [
-                { "chart": "Incoming Leads", "width": "Full" },
-                { "chart": "Opportunity Trends", "width": "Full"},
-                { "chart": "Won Opportunities", "width": "Full" },
-                { "chart": "Territory Wise Opportunity Count", "width": "Half"},
-                { "chart": "Opportunities via Campaigns", "width": "Half" },
-                { "chart": "Territory Wise Sales", "width": "Full"},
-                { "chart": "Lead Source", "width": "Half"}
-            ],
-            "cards": [
-                { "card": "New Lead (Last 1 Month)" },
-                { "card": "New Opportunity (Last 1 Month)" },
-                { "card": "Won Opportunity (Last 1 Month)" },
-                { "card": "Open Opportunity"},
-            ]
-        }]
-
-def get_company_for_dashboards():
-	company = frappe.defaults.get_defaults().company
-	if company:
-		return company
-	else:
-		company_list = frappe.get_list("Company")
-		if company_list:
-			return company_list[0].name
-	return None
-
-def get_charts():
-	company = get_company_for_dashboards()
-
-	return [{
-        "name": "Incoming Leads",
-        "doctype": "Dashboard Chart",
-        "time_interval": "Yearly",
-        "chart_type": "Count",
-        "chart_name": _("Incoming Leads"),
-        "timespan": "Last Quarter",
-        "time_interval": "Weekly",
-        "document_type": "Lead",
-        "based_on": "creation",
-        'is_public': 1,
-        'timeseries': 1,
-        "owner": "Administrator",
-        "filters_json": json.dumps([]),
-        "type": "Bar"
-    },
-    {
-        "name": "Opportunity Trends",
-        "doctype": "Dashboard Chart",
-        "time_interval": "Yearly",
-        "chart_type": "Count",
-        "chart_name": _("Opportunity Trends"),
-        "timespan": "Last Quarter",
-        "time_interval": "Weekly",
-        "document_type": "Opportunity",
-        "based_on": "creation",
-        'is_public': 1,
-        'timeseries': 1,
-        "owner": "Administrator",
-        "filters_json": json.dumps([["Opportunity", "company", "=", company, False]]),
-        "type": "Bar"
-    },
-    {
-        "name": "Opportunities via Campaigns",
-        "chart_name": _("Opportunities via Campaigns"),
-        "doctype": "Dashboard Chart",
-        "chart_type": "Group By",
-        "group_by_type": "Count",
-        "group_by_based_on": "campaign",
-        "document_type": "Opportunity",
-        'is_public': 1,
-        'timeseries': 1,
-        "owner": "Administrator",
-        "filters_json": json.dumps([["Opportunity", "company", "=", company, False]]),
-        "type": "Pie",
-        "custom_options": json.dumps({
-            "truncateLegends": 1,
-            "maxSlices": 8
-        })
-    },
-    {
-        "name": "Won Opportunities",
-        "doctype": "Dashboard Chart",
-        "time_interval": "Yearly",
-        "chart_type": "Count",
-        "chart_name": _("Won Opportunities"),
-        "timespan": "Last Year",
-        "time_interval": "Monthly",
-        "document_type": "Opportunity",
-        "based_on": "modified",
-        'is_public': 1,
-        'timeseries': 1,
-        "owner": "Administrator",
-        "filters_json": json.dumps([
-            ["Opportunity", "company", "=", company, False],
-            ["Opportunity", "status", "=", "Converted", False]]),
-        "type": "Bar"
-    },
-    {
-        "name": "Territory Wise Opportunity Count",
-        "doctype": "Dashboard Chart",
-        "chart_type": "Group By",
-        "group_by_type": "Count",
-        "group_by_based_on": "territory",
-        "chart_name": _("Territory Wise Opportunity Count"),
-        "document_type": "Opportunity",
-        'is_public': 1,
-        "filters_json": json.dumps([
-            ["Opportunity", "company", "=", company, False]
-        ]),
-        "owner": "Administrator",
-        "type": "Donut",
-        "custom_options": json.dumps({
-            "truncateLegends": 1,
-            "maxSlices": 8
-        })
-    },
-    {
-        "name": "Territory Wise Sales",
-        "doctype": "Dashboard Chart",
-        "chart_type": "Group By",
-        "group_by_type": "Sum",
-        "group_by_based_on": "territory",
-        "chart_name": _("Territory Wise Sales"),
-        "aggregate_function_based_on": "opportunity_amount",
-        "document_type": "Opportunity",
-        'is_public': 1,
-        "owner": "Administrator",
-        "filters_json": json.dumps([
-            ["Opportunity", "company", "=", company, False],
-            ["Opportunity", "status", "=", "Converted", False]
-        ]),
-        "type": "Bar"
-    },
-    {
-        "name": "Lead Source",
-        "doctype": "Dashboard Chart",
-        "chart_type": "Group By",
-        "group_by_type": "Count",
-        "group_by_based_on": "source",
-        "chart_name": _("Lead Source"),
-        "document_type": "Lead",
-        'is_public': 1,
-        "owner": "Administrator",
-        "type": "Pie",
-        "custom_options": json.dumps({
-            "truncateLegends": 1,
-            "maxSlices": 8
-        })
-    }]
-
-def get_number_cards():
-	return [{
-        "doctype": "Number Card",
-        "document_type": "Lead",
-        "name": "New Lead (Last 1 Month)",
-        "filters_json": json.dumps([["Lead","creation","Previous","1 month",False]]),
-        "function": "Count",
-        "is_public": 1,
-        "label": _("New Lead (Last 1 Month)"),
-        "show_percentage_stats": 1,
-        "stats_time_interval": "Daily"
-    },
-    {
-        "doctype": "Number Card",
-        "document_type": "Opportunity",
-        "name": "New Opportunity (Last 1 Month)",
-        "filters_json": json.dumps([["Opportunity","creation","Previous","1 month",False]]),
-        "function": "Count",
-        "is_public": 1,
-        "label": _("New Opportunity (Last 1 Month)"),
-        "show_percentage_stats": 1,
-        "stats_time_interval": "Daily"
-    },
-    {
-        "doctype": "Number Card",
-        "document_type": "Opportunity",
-        "name": "Won Opportunity (Last 1 Month)",
-        "filters_json": json.dumps([["Opportunity","creation","Previous","1 month",False]]),
-        "function": "Count",
-        "is_public": 1,
-        "label": _("Won Opportunity (Last 1 Month)"),
-        "show_percentage_stats": 1,
-        "stats_time_interval": "Daily"
-    },
-    {
-        "doctype": "Number Card",
-        "document_type": "Opportunity",
-        "name": "Open Opportunity",
-        "filters_json": json.dumps([["Opportunity","status","=","Open",False]]),
-        "function": "Count",
-        "is_public": 1,
-        "label": _("Open Opportunity"),
-        "show_percentage_stats": 1,
-        "stats_time_interval": "Daily"
-    }] 
\ No newline at end of file
diff --git a/erpnext/crm/doctype/contract/contract.json b/erpnext/crm/doctype/contract/contract.json
index e04ad30..0026e4a 100755
--- a/erpnext/crm/doctype/contract/contract.json
+++ b/erpnext/crm/doctype/contract/contract.json
@@ -29,6 +29,9 @@
   "requires_fulfilment",
   "fulfilment_deadline",
   "fulfilment_terms",
+  "authorised_by_section",
+  "signee_company",
+  "signed_by_company",
   "sb_references",
   "document_type",
   "cb_links",
@@ -223,10 +226,28 @@
    "options": "Contract",
    "print_hide": 1,
    "read_only": 1
+  },
+  {
+   "fieldname": "signee_company",
+   "fieldtype": "Signature",
+   "label": "Signee (Company)"
+  },
+  {
+   "fieldname": "signed_by_company",
+   "fieldtype": "Link",
+   "label": "Signed By (Company)",
+   "options": "User",
+   "read_only": 1
+  },
+  {
+   "fieldname": "authorised_by_section",
+   "fieldtype": "Section Break",
+   "label": "Authorised By"
   }
  ],
  "is_submittable": 1,
- "modified": "2019-09-30 00:56:41.559681",
+ "links": [],
+ "modified": "2020-03-30 06:56:07.257932",
  "modified_by": "Administrator",
  "module": "CRM",
  "name": "Contract",
diff --git a/erpnext/crm/doctype/contract/contract.py b/erpnext/crm/doctype/contract/contract.py
index 18444cc..c39397b 100644
--- a/erpnext/crm/doctype/contract/contract.py
+++ b/erpnext/crm/doctype/contract/contract.py
@@ -29,6 +29,9 @@
 		self.update_contract_status()
 		self.update_fulfilment_status()
 
+	def before_submit(self):
+		self.signed_by_company = frappe.session.user
+
 	def before_update_after_submit(self):
 		self.update_contract_status()
 		self.update_fulfilment_status()
diff --git a/erpnext/crm/doctype/contract_template/contract_template.json b/erpnext/crm/doctype/contract_template/contract_template.json
index b883ce2..ef9974f 100644
--- a/erpnext/crm/doctype/contract_template/contract_template.json
+++ b/erpnext/crm/doctype/contract_template/contract_template.json
@@ -1,306 +1,106 @@
 {
- "allow_copy": 0, 
- "allow_guest_to_view": 0, 
- "allow_import": 0, 
- "allow_rename": 0, 
- "autoname": "field:title", 
- "beta": 0, 
- "creation": "2018-04-16 06:44:48.791312", 
- "custom": 0, 
- "docstatus": 0, 
- "doctype": "DocType", 
- "document_type": "", 
- "editable_grid": 1, 
- "engine": "InnoDB", 
+ "actions": [],
+ "allow_rename": 1,
+ "autoname": "field:title",
+ "creation": "2018-04-16 06:44:48.791312",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "title",
+  "contract_terms",
+  "sb_fulfilment",
+  "requires_fulfilment",
+  "fulfilment_terms"
+ ],
  "fields": [
   {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "title", 
-   "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": "Title", 
-   "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": "title",
+   "fieldtype": "Data",
+   "label": "Title",
+   "unique": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "sb_terms", 
-   "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": "", 
-   "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": "contract_terms",
+   "fieldtype": "Text Editor",
+   "label": "Contract Terms and Conditions",
+   "read_only": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "contract_terms", 
-   "fieldtype": "Text Editor", 
-   "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": "Contract Terms and Conditions", 
-   "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, 
-   "unique": 0
-  }, 
+   "fieldname": "sb_fulfilment",
+   "fieldtype": "Section Break"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "sb_fulfilment", 
-   "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": "", 
-   "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": "requires_fulfilment",
+   "fieldtype": "Check",
+   "label": "Requires Fulfilment"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "requires_fulfilment", 
-   "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": "Requires Fulfilment", 
-   "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
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "depends_on": "eval:doc.requires_fulfilment==1", 
-   "fieldname": "fulfilment_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": "Fulfilment Terms and Conditions", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Contract Template Fulfilment Terms", 
-   "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
+   "depends_on": "eval:doc.requires_fulfilment==1",
+   "fieldname": "fulfilment_terms",
+   "fieldtype": "Table",
+   "label": "Fulfilment Terms and Conditions",
+   "options": "Contract Template Fulfilment 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-04-17 07:36:05.217599", 
- "modified_by": "Administrator", 
- "module": "CRM", 
- "name": "Contract Template", 
- "name_case": "", 
- "owner": "Administrator", 
+ ],
+ "links": [],
+ "modified": "2020-06-03 00:24:58.179816",
+ "modified_by": "Administrator",
+ "module": "CRM",
+ "name": "Contract 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": "Sales Manager", 
-   "set_user_permissions": 0, 
-   "share": 1, 
-   "submit": 0, 
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "export": 1,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "Sales 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": "Purchase Manager", 
-   "set_user_permissions": 0, 
-   "share": 1, 
-   "submit": 0, 
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "export": 1,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "Purchase 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": "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
   }
- ], 
- "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/crm/doctype/lead/lead.py b/erpnext/crm/doctype/lead/lead.py
index ec7d14d..315d298 100644
--- a/erpnext/crm/doctype/lead/lead.py
+++ b/erpnext/crm/doctype/lead/lead.py
@@ -114,10 +114,12 @@
 	def set_lead_name(self):
 		if not self.lead_name:
 			# Check for leads being created through data import
-			if not self.company_name and not self.flags.ignore_mandatory:
+			if not self.company_name and not self.email_id and not self.flags.ignore_mandatory:
 				frappe.throw(_("A Lead requires either a person's name or an organization's name"))
-
-			self.lead_name = self.company_name
+			elif self.company_name:
+				self.lead_name = self.company_name
+			else:
+				self.lead_name = self.email_id.split("@")[0]
 
 	def set_title(self):
 		if self.organization_lead:
diff --git a/erpnext/crm/doctype/opportunity/opportunity.js b/erpnext/crm/doctype/opportunity/opportunity.js
index f1b8171..08958b7 100644
--- a/erpnext/crm/doctype/opportunity/opportunity.js
+++ b/erpnext/crm/doctype/opportunity/opportunity.js
@@ -30,7 +30,6 @@
 	},
 
 	party_name: function(frm) {
-		frm.toggle_display("contact_info", frm.doc.party_name);
 		frm.trigger('set_contact_link');
 
 		if (frm.doc.opportunity_from == "Customer") {
@@ -48,10 +47,6 @@
 		frm.get_field("items").grid.set_multiple_add("item_code", "qty");
 	},
 
-	with_items: function(frm) {
-		frm.trigger('toggle_mandatory');
-	},
-
 	customer_address: function(frm, cdt, cdn) {
 		erpnext.utils.get_address_display(frm, 'customer_address', 'address_display', false);
 	},
@@ -59,15 +54,19 @@
 	contact_person: erpnext.utils.get_contact_details,
 
 	opportunity_from: function(frm) {
+		frm.trigger('setup_opportunity_from');
+
+		frm.set_value("party_name", "");
+	},
+
+	setup_opportunity_from: function(frm) {
 		frm.trigger('setup_queries');
-		frm.toggle_reqd("party_name", frm.doc.opportunity_from);
 		frm.trigger("set_dynamic_field_label");
 	},
 
 	refresh: function(frm) {
 		var doc = frm.doc;
-		frm.events.opportunity_from(frm);
-		frm.trigger('toggle_mandatory');
+		frm.trigger('setup_opportunity_from');
 		erpnext.toggle_naming_series();
 
 		if(!doc.__islocal && doc.status!=="Lost") {
@@ -76,6 +75,11 @@
 					function() {
 						frm.trigger("make_supplier_quotation")
 					}, __('Create'));
+
+				frm.add_custom_button(__('Request For Quotation'),
+					function() {
+						frm.trigger("make_request_for_quotation")
+					}, __('Create'));
 			}
 
 			frm.add_custom_button(__('Quotation'),
@@ -113,7 +117,6 @@
 	},
 
 	set_dynamic_field_label: function(frm){
-
 		if (frm.doc.opportunity_from) {
 			frm.set_df_property("party_name", "label", frm.doc.opportunity_from);
 		}
@@ -122,13 +125,17 @@
 	make_supplier_quotation: function(frm) {
 		frappe.model.open_mapped_doc({
 			method: "erpnext.crm.doctype.opportunity.opportunity.make_supplier_quotation",
-			frm: cur_frm
+			frm: frm
 		})
 	},
 
-	toggle_mandatory: function(frm) {
-		frm.toggle_reqd("items", frm.doc.with_items ? 1:0);
-	}
+	make_request_for_quotation: function(frm) {
+		frappe.model.open_mapped_doc({
+			method: "erpnext.crm.doctype.opportunity.opportunity.make_request_for_quotation",
+			frm: frm
+		})
+	},
+
 })
 
 // TODO commonify this code
diff --git a/erpnext/crm/doctype/opportunity/opportunity.json b/erpnext/crm/doctype/opportunity/opportunity.json
index 6a54c5f..545e232 100644
--- a/erpnext/crm/doctype/opportunity/opportunity.json
+++ b/erpnext/crm/doctype/opportunity/opportunity.json
@@ -254,6 +254,7 @@
    "fieldname": "items",
    "fieldtype": "Table",
    "label": "Items",
+   "mandatory_depends_on": "eval: doc.with_items == 1",
    "oldfieldname": "enquiry_details",
    "oldfieldtype": "Table",
    "options": "Opportunity Item"
@@ -423,7 +424,7 @@
  "icon": "fa fa-info-sign",
  "idx": 195,
  "links": [],
- "modified": "2020-04-07 09:05:39.391109",
+ "modified": "2020-07-14 16:49:15.888503",
  "modified_by": "Administrator",
  "module": "CRM",
  "name": "Opportunity",
diff --git a/erpnext/crm/module_onboarding/crm/crm.json b/erpnext/crm/module_onboarding/crm/crm.json
index 44d672a..8315218 100644
--- a/erpnext/crm/module_onboarding/crm/crm.json
+++ b/erpnext/crm/module_onboarding/crm/crm.json
@@ -16,7 +16,7 @@
  "documentation_url": "https://docs.erpnext.com/docs/user/manual/en/CRM",
  "idx": 0,
  "is_complete": 0,
- "modified": "2020-05-28 21:07:41.278784",
+ "modified": "2020-07-08 14:05:42.644448",
  "modified_by": "Administrator",
  "module": "CRM",
  "name": "CRM",
@@ -35,8 +35,7 @@
    "step": "Create and Send Quotation"
   }
  ],
- "subtitle": "Lead, Opportunity, Customer and more.",
- "success_message": "CRM Module is all Set Up!",
- "title": "Let's Set Up Your CRM.",
- "user_can_dismiss": 1
+ "subtitle": "Lead, Opportunity, Customer, and more.",
+ "success_message": "The CRM Module is all set up!",
+ "title": "Let's Set Up Your CRM."
 }
\ No newline at end of file
diff --git "a/erpnext/crm/number_card/new_lead_\050last_1_month\051/new_lead_\050last_1_month\051.json" "b/erpnext/crm/number_card/new_lead_\050last_1_month\051/new_lead_\050last_1_month\051.json"
new file mode 100644
index 0000000..4511f54
--- /dev/null
+++ "b/erpnext/crm/number_card/new_lead_\050last_1_month\051/new_lead_\050last_1_month\051.json"
@@ -0,0 +1,21 @@
+{
+ "creation": "2020-07-20 20:17:15.870736",
+ "docstatus": 0,
+ "doctype": "Number Card",
+ "document_type": "Lead",
+ "dynamic_filters_json": "[[\"Lead\",\"company\",\"=\",\"frappe.defaults.get_user_default(\\\"Company\\\")\"]]",
+ "filters_json": "[[\"Lead\",\"creation\",\"Timespan\",\"last month\",false]]",
+ "function": "Count",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "label": "New Lead (Last 1 Month)",
+ "modified": "2020-07-22 16:15:17.274972",
+ "modified_by": "Administrator",
+ "module": "CRM",
+ "name": "New Lead (Last 1 Month)",
+ "owner": "Administrator",
+ "show_percentage_stats": 1,
+ "stats_time_interval": "Daily",
+ "type": "Document Type"
+}
\ No newline at end of file
diff --git "a/erpnext/crm/number_card/new_opportunity_\050last_1_month\051/new_opportunity_\050last_1_month\051.json" "b/erpnext/crm/number_card/new_opportunity_\050last_1_month\051/new_opportunity_\050last_1_month\051.json"
new file mode 100644
index 0000000..90997b7
--- /dev/null
+++ "b/erpnext/crm/number_card/new_opportunity_\050last_1_month\051/new_opportunity_\050last_1_month\051.json"
@@ -0,0 +1,21 @@
+{
+ "creation": "2020-07-20 20:17:15.897112",
+ "docstatus": 0,
+ "doctype": "Number Card",
+ "document_type": "Opportunity",
+ "dynamic_filters_json": "[[\"Opportunity\",\"company\",\"=\",\"frappe.defaults.get_user_default(\\\"Company\\\")\"]]",
+ "filters_json": "[[\"Opportunity\",\"creation\",\"Timespan\",\"last month\",false]]",
+ "function": "Count",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "label": "New Opportunity (Last 1 Month)",
+ "modified": "2020-07-22 16:07:27.910432",
+ "modified_by": "Administrator",
+ "module": "CRM",
+ "name": "New Opportunity (Last 1 Month)",
+ "owner": "Administrator",
+ "show_percentage_stats": 1,
+ "stats_time_interval": "Daily",
+ "type": "Document Type"
+}
\ No newline at end of file
diff --git a/erpnext/crm/number_card/open_opportunity/open_opportunity.json b/erpnext/crm/number_card/open_opportunity/open_opportunity.json
new file mode 100644
index 0000000..6e06ed6
--- /dev/null
+++ b/erpnext/crm/number_card/open_opportunity/open_opportunity.json
@@ -0,0 +1,21 @@
+{
+ "creation": "2020-07-20 20:17:15.948113",
+ "docstatus": 0,
+ "doctype": "Number Card",
+ "document_type": "Opportunity",
+ "dynamic_filters_json": "[[\"Opportunity\",\"status\",\"=\",\"frappe.defaults.get_user_default(\\\"Company\\\")\"]]",
+ "filters_json": "[[\"Opportunity\",\"company\",\"=\",null,false]]",
+ "function": "Count",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "label": "Open Opportunity",
+ "modified": "2020-07-22 16:16:16.420446",
+ "modified_by": "Administrator",
+ "module": "CRM",
+ "name": "Open Opportunity",
+ "owner": "Administrator",
+ "show_percentage_stats": 1,
+ "stats_time_interval": "Daily",
+ "type": "Document Type"
+}
\ No newline at end of file
diff --git "a/erpnext/crm/number_card/won_opportunity_\050last_1_month\051/won_opportunity_\050last_1_month\051.json" "b/erpnext/crm/number_card/won_opportunity_\050last_1_month\051/won_opportunity_\050last_1_month\051.json"
new file mode 100644
index 0000000..ba0c07e
--- /dev/null
+++ "b/erpnext/crm/number_card/won_opportunity_\050last_1_month\051/won_opportunity_\050last_1_month\051.json"
@@ -0,0 +1,21 @@
+{
+ "creation": "2020-07-20 20:17:15.922486",
+ "docstatus": 0,
+ "doctype": "Number Card",
+ "document_type": "Opportunity",
+ "dynamic_filters_json": "[[\"Opportunity\",\"company\",\"=\",\"frappe.defaults.get_user_default(\\\"Company\\\")\"]]",
+ "filters_json": "[[\"Opportunity\",\"creation\",\"Timespan\",\"last month\",false]]",
+ "function": "Count",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "label": "Won Opportunity (Last 1 Month)",
+ "modified": "2020-07-22 16:15:53.088837",
+ "modified_by": "Administrator",
+ "module": "CRM",
+ "name": "Won Opportunity (Last 1 Month)",
+ "owner": "Administrator",
+ "show_percentage_stats": 1,
+ "stats_time_interval": "Daily",
+ "type": "Document Type"
+}
\ No newline at end of file
diff --git a/erpnext/crm/report/lead_owner_efficiency/lead_owner_efficiency.py b/erpnext/crm/report/lead_owner_efficiency/lead_owner_efficiency.py
index 6172a75..8fe16a2 100644
--- a/erpnext/crm/report/lead_owner_efficiency/lead_owner_efficiency.py
+++ b/erpnext/crm/report/lead_owner_efficiency/lead_owner_efficiency.py
@@ -17,7 +17,8 @@
 		{
 			"fieldname": "lead_owner",
 			"label": _("Lead Owner"),
-			"fieldtype": "Data",
+			"fieldtype": "Link",
+			"options": "User",
 			"width": "130"
 		},
 		{
@@ -68,4 +69,4 @@
 			"fieldtype": "Float",
 			"width": "100"
 		}
-	]
\ No newline at end of file
+	]
diff --git a/erpnext/education/api.py b/erpnext/education/api.py
index 1a19716..fe033d4 100644
--- a/erpnext/education/api.py
+++ b/erpnext/education/api.py
@@ -104,6 +104,7 @@
 	student_attendance.date = date
 	student_attendance.status = status
 	student_attendance.save()
+	student_attendance.submit()
 
 
 @frappe.whitelist()
@@ -363,9 +364,9 @@
 		select
 			name as program_enrollment, student_name, program, student_batch_name as student_batch,
 			student_category, academic_term, academic_year
-		from 
+		from
 			`tabProgram Enrollment`
-		where 
+		where
 			student = %s and academic_year = %s
 		order by creation''', (student, current_academic_year), as_dict=1)
 
diff --git a/erpnext/education/doctype/academic_term/academic_term_dashboard.py b/erpnext/education/doctype/academic_term/academic_term_dashboard.py
new file mode 100644
index 0000000..871e0f3
--- /dev/null
+++ b/erpnext/education/doctype/academic_term/academic_term_dashboard.py
@@ -0,0 +1,25 @@
+from __future__ import unicode_literals
+from frappe import _
+
+def get_data():
+	return {
+		'fieldname': 'academic_term',
+		'transactions': [
+			{
+				'label': _('Student'),
+				'items': ['Student Applicant', 'Student Group', 'Student Log']
+			},
+			{
+				'label': _('Fee'),
+				'items': ['Fees', 'Fee Schedule', 'Fee Structure']
+			},
+			{
+				'label': _('Program'),
+				'items': ['Program Enrollment']
+			},
+			{
+				'label': _('Assessment'),
+				'items': ['Assessment Plan', 'Assessment Result']
+			}
+		]
+	}
\ No newline at end of file
diff --git a/erpnext/education/doctype/academic_year/academic_year.js b/erpnext/education/doctype/academic_year/academic_year.js
index 21caa63..0e86198 100644
--- a/erpnext/education/doctype/academic_year/academic_year.js
+++ b/erpnext/education/doctype/academic_year/academic_year.js
@@ -1,10 +1,2 @@
-frappe.ui.form.on("Academic Year", "refresh", function(frm) {
-	if(!frm.doc.__islocal) {
-		frm.add_custom_button(__("Student Group"), function() {
-			frappe.route_options = {
-				academic_year: frm.doc.name
-			}
-			frappe.set_route("List", "Student Group");
-		});
-	}
+frappe.ui.form.on("Academic Year", {
 });
\ No newline at end of file
diff --git a/erpnext/education/doctype/academic_year/academic_year_dashboard.py b/erpnext/education/doctype/academic_year/academic_year_dashboard.py
new file mode 100644
index 0000000..f27f7d1
--- /dev/null
+++ b/erpnext/education/doctype/academic_year/academic_year_dashboard.py
@@ -0,0 +1,25 @@
+from __future__ import unicode_literals
+from frappe import _
+
+def get_data():
+	return {
+		'fieldname': 'academic_year',
+		'transactions': [
+			{
+				'label': _('Student'),
+				'items': ['Student Admission', 'Student Applicant', 'Student Group', 'Student Log']
+			},
+			{
+				'label': _('Fee'),
+				'items': ['Fees', 'Fee Schedule', 'Fee Structure']
+			},
+			{
+				'label': _('Academic Term and Program'),
+				'items': ['Academic Term', 'Program Enrollment']
+			},
+			{
+				'label': _('Assessment'),
+				'items': ['Assessment Plan', 'Assessment Result']
+			}
+		]
+	}
\ No newline at end of file
diff --git a/erpnext/education/doctype/article/article.js b/erpnext/education/doctype/article/article.js
index 4c9c6f0..edfec26 100644
--- a/erpnext/education/doctype/article/article.js
+++ b/erpnext/education/doctype/article/article.js
@@ -3,6 +3,54 @@
 
 frappe.ui.form.on('Article', {
 	refresh: function(frm) {
+		if (!frm.doc.__islocal) {
+			frm.add_custom_button(__('Add to Topics'), function() {
+				frm.trigger('add_article_to_topics');
+			}, __('Action'));
+		}
+	},
 
+	add_article_to_topics: function(frm) {
+		get_topics_without_article(frm.doc.name).then(r => {
+			if (r.message.length) {
+				frappe.prompt([
+					{
+						fieldname: 'topics',
+						label: __('Topics'),
+						fieldtype: 'MultiSelectPills',
+						get_data: function() {
+							return r.message;
+						}
+					}
+				],
+				function(data) {
+					frappe.call({
+						method: 'erpnext.education.doctype.topic.topic.add_content_to_topics',
+						args: {
+							'content_type': 'Article',
+							'content': frm.doc.name,
+							'topics': data.topics,
+						},
+						callback: function(r) {
+							if (!r.exc) {
+								frm.reload_doc();
+							}
+						},
+						freeze: true,
+						freeze_message: __('...Adding Article to Topics')
+					});
+				}, __('Add Article to Topics'), __('Add'));
+			} else {
+				frappe.msgprint(__('This article is already added to the existing topics'));
+			}
+		});
 	}
 });
+
+let get_topics_without_article = function(article) {
+	return frappe.call({
+		type: 'GET',
+		method: 'erpnext.education.doctype.article.article.get_topics_without_article',
+		args: {'article': article}
+	});
+};
\ No newline at end of file
diff --git a/erpnext/education/doctype/article/article.py b/erpnext/education/doctype/article/article.py
index 7dc850b..8ba367d 100644
--- a/erpnext/education/doctype/article/article.py
+++ b/erpnext/education/doctype/article/article.py
@@ -7,9 +7,15 @@
 from frappe.model.document import Document
 
 class Article(Document):
-
-
 	def get_article(self):
 		pass
 
-
+@frappe.whitelist()
+def get_topics_without_article(article):
+	data = []
+	for entry in frappe.db.get_all('Topic'):
+		topic = frappe.get_doc('Topic', entry.name)
+		topic_contents = [tc.content for tc in topic.topic_content]
+		if not topic_contents or article not in topic_contents:
+			data.append(topic.name)
+	return data
\ No newline at end of file
diff --git a/erpnext/education/doctype/assessment_group/assessment_group_dashboard.py b/erpnext/education/doctype/assessment_group/assessment_group_dashboard.py
new file mode 100644
index 0000000..2649d4b
--- /dev/null
+++ b/erpnext/education/doctype/assessment_group/assessment_group_dashboard.py
@@ -0,0 +1,15 @@
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
+# License: GNU General Public License v3. See license.txt
+from __future__ import unicode_literals
+from frappe import _
+
+def get_data():
+	return {
+		'fieldname': 'assessment_group',
+		'transactions': [
+			{
+				'label': _('Assessment'),
+				'items': ['Assessment Plan', 'Assessment Result']
+			}
+		]
+	}
\ No newline at end of file
diff --git a/erpnext/education/doctype/assessment_plan/assessment_plan.js b/erpnext/education/doctype/assessment_plan/assessment_plan.js
index 0cb642b..c4c5614 100644
--- a/erpnext/education/doctype/assessment_plan/assessment_plan.js
+++ b/erpnext/education/doctype/assessment_plan/assessment_plan.js
@@ -2,9 +2,9 @@
 // For license information, please see license.txt
 
 
-frappe.ui.form.on("Assessment Plan", {
+frappe.ui.form.on('Assessment Plan', {
 	onload: function(frm) {
-		frm.set_query("assessment_group", function(doc, cdt, cdn) {
+		frm.set_query('assessment_group', function(doc, cdt, cdn) {
 			return{
 				filters: {
 					'is_group': 0
@@ -22,20 +22,20 @@
 
 	refresh: function(frm) {
 		if (frm.doc.docstatus == 1) {
-			frm.add_custom_button(__("Assessment Result"), function() {
+			frm.add_custom_button(__('Assessment Result Tool'), function() {
 				frappe.route_options = {
 					assessment_plan: frm.doc.name,
 					student_group: frm.doc.student_group
 				}
-				frappe.set_route("Form", "Assessment Result Tool");
-			});
+				frappe.set_route('Form', 'Assessment Result Tool');
+			}, __('Tools'));
 		}
 	},
 
 	course: function(frm) {
 		if (frm.doc.course && frm.doc.maximum_assessment_score) {
 			frappe.call({
-				method: "erpnext.education.api.get_assessment_criteria",
+				method: 'erpnext.education.api.get_assessment_criteria',
 				args: {
 					course: frm.doc.course
 				},
@@ -43,12 +43,12 @@
 					if (r.message) {
 						frm.doc.assessment_criteria = [];
 						$.each(r.message, function(i, d) {
-							var row = frappe.model.add_child(frm.doc, "Assessment Plan Criteria", "assessment_criteria");
+							var row = frappe.model.add_child(frm.doc, 'Assessment Plan Criteria', 'assessment_criteria');
 							row.assessment_criteria = d.assessment_criteria;
 							row.maximum_score = d.weightage / 100 * frm.doc.maximum_assessment_score;
 						});
 					}
-					refresh_field("assessment_criteria");
+					refresh_field('assessment_criteria');
 
 				}
 			});
@@ -56,6 +56,6 @@
 	},
 
 	maximum_assessment_score: function(frm) {
-		frm.trigger("course");
+		frm.trigger('course');
 	}
 });
\ No newline at end of file
diff --git a/erpnext/education/doctype/assessment_plan/assessment_plan_dashboard.py b/erpnext/education/doctype/assessment_plan/assessment_plan_dashboard.py
index c36dfb1..5e6c29d 100644
--- a/erpnext/education/doctype/assessment_plan/assessment_plan_dashboard.py
+++ b/erpnext/education/doctype/assessment_plan/assessment_plan_dashboard.py
@@ -6,12 +6,16 @@
 def get_data():
 	return {
 		'fieldname': 'assessment_plan',
-		'non_standard_fieldnames': {
-		},
 		'transactions': [
 			{
 				'label': _('Assessment'),
 				'items': ['Assessment Result']
 			}
+		],
+		'reports': [
+			{
+				'label': _('Report'),
+				'items': ['Assessment Plan Status']
+			}
 		]
 	}
\ No newline at end of file
diff --git a/erpnext/education/doctype/assessment_result/assessment_result.js b/erpnext/education/doctype/assessment_result/assessment_result.js
index 84865ca..12fdd91 100644
--- a/erpnext/education/doctype/assessment_result/assessment_result.js
+++ b/erpnext/education/doctype/assessment_result/assessment_result.js
@@ -1,7 +1,13 @@
 // Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
 // For license information, please see license.txt
 
-frappe.ui.form.on("Assessment Result", {
+frappe.ui.form.on('Assessment Result', {
+	refresh: function(frm) {
+		if (!frm.doc.__islocal) {
+			frm.trigger('setup_chart');
+		}
+	},
+
 	onload: function(frm) {
 		frm.set_query('assessment_plan', function(){
 			return {
@@ -15,7 +21,7 @@
 	assessment_plan: function(frm) {
 		if (frm.doc.assessment_plan) {
 			frappe.call({
-				method: "erpnext.education.api.get_assessment_details",
+				method: 'erpnext.education.api.get_assessment_details',
 				args: {
 					assessment_plan: frm.doc.assessment_plan
 				},
@@ -23,40 +29,75 @@
 					if (r.message) {
 						frm.doc.details = [];
 						$.each(r.message, function(i, d) {
-							var row = frappe.model.add_child(frm.doc, "Assessment Result Detail", "details");
+							var row = frappe.model.add_child(frm.doc, 'Assessment Result Detail', 'details');
 							row.assessment_criteria = d.assessment_criteria;
 							row.maximum_score = d.maximum_score;
 						});
 					}
-					refresh_field("details");
+					refresh_field('details');
 				}
 			});
 		}
+	},
+
+	setup_chart: function(frm) {
+		let labels = [];
+		let maximum_scores = [];
+		let scores = [];
+		$.each(frm.doc.details, function(_i, e) {
+			labels.push(e.assessment_criteria);
+			maximum_scores.push(e.maximum_score);
+			scores.push(e.score);
+		});
+
+		if (labels.length && maximum_scores.length && scores.length) {
+			frm.dashboard.chart_area.empty().removeClass('hidden');
+			new frappe.Chart('.form-graph', {
+				title: 'Assessment Results',
+				data: {
+					labels: labels,
+					datasets: [
+						{
+							name: 'Maximum Score',
+							chartType: 'bar',
+							values: maximum_scores,
+						},
+						{
+							name: 'Score Obtained',
+							chartType: 'bar',
+							values: scores,
+						}
+					]
+				},
+				colors: ['#4CA746', '#98D85B'],
+				type: 'bar'
+			});
+		}
 	}
 });
 
-frappe.ui.form.on("Assessment Result Detail", {
+frappe.ui.form.on('Assessment Result Detail', {
 	score: function(frm, cdt, cdn) {
 		var d  = locals[cdt][cdn];
 
 		if(!d.maximum_score || !frm.doc.grading_scale) {
-			d.score = "";
-			frappe.throw(__("Please fill in all the details to generate Assessment Result."));
+			d.score = '';
+			frappe.throw(__('Please fill in all the details to generate Assessment Result.'));
 		}
 
 		if (d.score > d.maximum_score) {
-			frappe.throw(__("Score cannot be greater than Maximum Score"));
+			frappe.throw(__('Score cannot be greater than Maximum Score'));
 		}
 		else {
 			frappe.call({
-				method: "erpnext.education.api.get_grade",
+				method: 'erpnext.education.api.get_grade',
 				args: {
 					grading_scale: frm.doc.grading_scale,
 					percentage: ((d.score/d.maximum_score) * 100)
 				},
 				callback: function(r) {
 					if (r.message) {
-						frappe.model.set_value(cdt, cdn, "grade", r.message);
+						frappe.model.set_value(cdt, cdn, 'grade', r.message);
 					}
 				}
 			});
diff --git a/erpnext/education/doctype/assessment_result/assessment_result_dashboard.py b/erpnext/education/doctype/assessment_result/assessment_result_dashboard.py
new file mode 100644
index 0000000..438379d
--- /dev/null
+++ b/erpnext/education/doctype/assessment_result/assessment_result_dashboard.py
@@ -0,0 +1,14 @@
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
+# License: GNU General Public License v3. See license.txt
+from __future__ import unicode_literals
+from frappe import _
+
+def get_data():
+	return {
+		'reports': [
+			{
+				'label': _('Reports'),
+				'items': ['Final Assessment Grades', 'Course wise Assessment Report']
+			}
+		]
+	}
\ No newline at end of file
diff --git a/erpnext/education/doctype/course/course.js b/erpnext/education/doctype/course/course.js
index 6932989..81e4a8c 100644
--- a/erpnext/education/doctype/course/course.js
+++ b/erpnext/education/doctype/course/course.js
@@ -1,41 +1,60 @@
-frappe.ui.form.on("Course", "refresh", function(frm) {
-	if(!cur_frm.doc.__islocal) {
-		frm.add_custom_button(__("Program"), function() {
-			frappe.route_options = {
-				"Program Course.course": frm.doc.name
-			}
-			frappe.set_route("List", "Program");
-		});
+frappe.ui.form.on('Course', {
+	refresh: function(frm) {
+		if (!cur_frm.doc.__islocal) {
+			frm.add_custom_button(__('Add to Programs'), function() {
+				frm.trigger('add_course_to_programs')
+			}, __('Action'));
+		}
 
-		frm.add_custom_button(__("Student Group"), function() {
-			frappe.route_options = {
-				course: frm.doc.name
+		frm.set_query('default_grading_scale', function(){
+			return {
+				filters: {
+					docstatus: 1
+				}
 			}
-			frappe.set_route("List", "Student Group");
 		});
+	},
 
-		frm.add_custom_button(__("Course Schedule"), function() {
-			frappe.route_options = {
-				course: frm.doc.name
+	add_course_to_programs: function(frm) {
+		get_programs_without_course(frm.doc.name).then(r => {
+			if (r.message.length) {
+				frappe.prompt([
+					{
+						fieldname: 'programs',
+						label: __('Programs'),
+						fieldtype: 'MultiSelectPills',
+						get_data: function() {
+							return r.message;
+						}
+					},
+					{
+						fieldtype: 'Check',
+						label: __('Is Mandatory'),
+						fieldname: 'mandatory',
+					}
+				],
+				function(data) {
+					frappe.call({
+						method: 'erpnext.education.doctype.course.course.add_course_to_programs',
+						args: {
+							'course': frm.doc.name,
+							'programs': data.programs,
+							'mandatory': data.mandatory
+						},
+						callback: function(r) {
+							if (!r.exc) {
+								frm.reload_doc();
+							}
+						},
+						freeze: true,
+						freeze_message: __('...Adding Course to Programs')
+					})
+				}, __('Add Course to Programs'), __('Add'));
+			} else {
+				frappe.msgprint(__('This course is already added to the existing programs'));
 			}
-			frappe.set_route("List", "Course Schedule");
-		});
-
-		frm.add_custom_button(__("Assessment Plan"), function() {
-			frappe.route_options = {
-				course: frm.doc.name
-			}
-			frappe.set_route("List", "Assessment Plan");
 		});
 	}
-
-	frm.set_query('default_grading_scale', function(){
-		return {
-			filters: {
-				docstatus: 1
-			}
-		}
-	});
 });
 
 frappe.ui.form.on('Course Topic', {
@@ -50,3 +69,11 @@
 		};
 	}
 });
+
+let get_programs_without_course = function(course) {
+	return frappe.call({
+		type: 'GET',
+		method: 'erpnext.education.doctype.course.course.get_programs_without_course',
+		args: {'course': course}
+	});
+}
\ No newline at end of file
diff --git a/erpnext/education/doctype/course/course.py b/erpnext/education/doctype/course/course.py
index 0747a22..06efa54 100644
--- a/erpnext/education/doctype/course/course.py
+++ b/erpnext/education/doctype/course/course.py
@@ -4,6 +4,7 @@
 
 from __future__ import unicode_literals
 import frappe
+import json
 from frappe.model.document import Document
 from frappe import _
 
@@ -17,12 +18,39 @@
 			for criteria in self.assessment_criteria:
 				total_weightage += criteria.weightage or 0
 			if total_weightage != 100:
-				frappe.throw(_("Total Weightage of all Assessment Criteria must be 100%"))
+				frappe.throw(_('Total Weightage of all Assessment Criteria must be 100%'))
 
 	def get_topics(self):
 		topic_data= []
 		for topic in self.topics:
-			topic_doc = frappe.get_doc("Topic", topic.topic)
+			topic_doc = frappe.get_doc('Topic', topic.topic)
 			if topic_doc.topic_content:
 				topic_data.append(topic_doc)
-		return topic_data
\ No newline at end of file
+		return topic_data
+
+
+@frappe.whitelist()
+def add_course_to_programs(course, programs, mandatory=False):
+	programs = json.loads(programs)
+	for entry in programs:
+		program = frappe.get_doc('Program', entry)
+		program.append('courses', {
+			'course': course,
+			'course_name': course,
+			'mandatory': mandatory
+		})
+		program.flags.ignore_mandatory = True
+		program.save()
+	frappe.db.commit()
+	frappe.msgprint(_('Course {0} has been added to all the selected programs successfully.').format(frappe.bold(course)),
+		title=_('Programs updated'), indicator='green')
+
+@frappe.whitelist()
+def get_programs_without_course(course):
+	data = []
+	for entry in frappe.db.get_all('Program'):
+		program = frappe.get_doc('Program', entry.name)
+		courses = [c.course for c in program.courses]
+		if not courses or course not in courses:
+			data.append(program.name)
+	return data
\ No newline at end of file
diff --git a/erpnext/education/doctype/course/course_dashboard.py b/erpnext/education/doctype/course/course_dashboard.py
index 752af29..8a570bd 100644
--- a/erpnext/education/doctype/course/course_dashboard.py
+++ b/erpnext/education/doctype/course/course_dashboard.py
@@ -6,12 +6,10 @@
 def get_data():
 	return {
 		'fieldname': 'course',
-		'non_standard_fieldnames': {
-		},
 		'transactions': [
 			{
-				'label': _('Course'),
-				'items': ['Course Enrollment', 'Course Schedule']
+				'label': _('Program and Course'),
+				'items': ['Program', 'Course Enrollment', 'Course Schedule']
 			},
 			{
 				'label': _('Student'),
@@ -19,7 +17,7 @@
 			},
 			{
 				'label': _('Assessment'),
-				'items': ['Assessment Plan']
+				'items': ['Assessment Plan', 'Assessment Result']
 			},
 		]
 	}
\ No newline at end of file
diff --git a/erpnext/education/doctype/course_enrollment/course_enrollment_dashboard.py b/erpnext/education/doctype/course_enrollment/course_enrollment_dashboard.py
new file mode 100644
index 0000000..b9dd457
--- /dev/null
+++ b/erpnext/education/doctype/course_enrollment/course_enrollment_dashboard.py
@@ -0,0 +1,15 @@
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
+# License: GNU General Public License v3. See license.txt
+from __future__ import unicode_literals
+from frappe import _
+
+def get_data():
+	return {
+		'fieldname': 'enrollment',
+		'transactions': [
+			{
+				'label': _('Activity'),
+				'items': ['Course Activity', 'Quiz Activity']
+			}
+		]
+	}
\ No newline at end of file
diff --git a/erpnext/education/doctype/course_schedule/course_schedule.js b/erpnext/education/doctype/course_schedule/course_schedule.js
index 692c2a8..4275f6e 100644
--- a/erpnext/education/doctype/course_schedule/course_schedule.js
+++ b/erpnext/education/doctype/course_schedule/course_schedule.js
@@ -4,13 +4,13 @@
 frappe.ui.form.on("Course Schedule", {
 	refresh: function(frm) {
 		if (!frm.doc.__islocal) {
-			frm.add_custom_button(__("Attendance"), function() {
+			frm.add_custom_button(__("Mark Attendance"), function() {
 				frappe.route_options = {
 					based_on: "Course Schedule",
 					course_schedule: frm.doc.name
 				}
 				frappe.set_route("Form", "Student Attendance Tool");
-			});
+			}).addClass("btn-primary");
 		}
 	}
 });
\ No newline at end of file
diff --git a/erpnext/education/doctype/course_schedule/course_schedule.json b/erpnext/education/doctype/course_schedule/course_schedule.json
index 7346cab..8c6746b 100644
--- a/erpnext/education/doctype/course_schedule/course_schedule.json
+++ b/erpnext/education/doctype/course_schedule/course_schedule.json
@@ -1,520 +1,520 @@
 {
- "allow_copy": 0, 
- "allow_guest_to_view": 0, 
- "allow_import": 1, 
- "allow_rename": 0, 
- "autoname": "naming_series:", 
- "beta": 0, 
- "creation": "2015-09-09 16:34:04.960369", 
- "custom": 0, 
- "docstatus": 0, 
- "doctype": "DocType", 
- "document_type": "Document", 
- "editable_grid": 0, 
- "engine": "InnoDB", 
+ "allow_copy": 0,
+ "allow_guest_to_view": 0,
+ "allow_import": 1,
+ "allow_rename": 0,
+ "autoname": "naming_series:",
+ "beta": 0,
+ "creation": "2015-09-09 16:34:04.960369",
+ "custom": 0,
+ "docstatus": 0,
+ "doctype": "DocType",
+ "document_type": "Document",
+ "editable_grid": 0,
+ "engine": "InnoDB",
  "fields": [
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "student_group", 
-   "fieldtype": "Link", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 1, 
-   "in_list_view": 0, 
-   "in_standard_filter": 1, 
-   "label": "Student Group", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Student Group", 
-   "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, 
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fieldname": "student_group",
+   "fieldtype": "Link",
+   "hidden": 0,
+   "ignore_user_permissions": 0,
+   "ignore_xss_filter": 0,
+   "in_filter": 0,
+   "in_global_search": 1,
+   "in_list_view": 0,
+   "in_standard_filter": 1,
+   "label": "Student Group",
+   "length": 0,
+   "no_copy": 0,
+   "options": "Student Group",
+   "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
-  }, 
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "instructor", 
-   "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": 1, 
-   "label": "Instructor", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Instructor", 
-   "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, 
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fieldname": "instructor",
+   "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": 1,
+   "label": "Instructor",
+   "length": 0,
+   "no_copy": 0,
+   "options": "Instructor",
+   "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
-  }, 
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fetch_from": "instructor.Instructor_name", 
-   "fieldname": "instructor_name", 
-   "fieldtype": "Read Only", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 1, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Instructor Name", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "", 
-   "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, 
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fetch_from": "instructor.Instructor_name",
+   "fieldname": "instructor_name",
+   "fieldtype": "Read Only",
+   "hidden": 0,
+   "ignore_user_permissions": 0,
+   "ignore_xss_filter": 0,
+   "in_filter": 0,
+   "in_global_search": 1,
+   "in_list_view": 0,
+   "in_standard_filter": 0,
+   "label": "Instructor Name",
+   "length": 0,
+   "no_copy": 0,
+   "options": "",
+   "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, 
-   "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, 
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 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
-  }, 
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "default": "", 
-   "fieldname": "naming_series", 
-   "fieldtype": "Select", 
-   "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": "Naming Series", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "EDU-CSH-.YYYY.-", 
-   "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": 1, 
-   "translatable": 0, 
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "default": "",
+   "fieldname": "naming_series",
+   "fieldtype": "Select",
+   "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": "Naming Series",
+   "length": 0,
+   "no_copy": 0,
+   "options": "EDU-CSH-.YYYY.-",
+   "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": 1,
+   "translatable": 0,
    "unique": 0
-  }, 
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "course", 
-   "fieldtype": "Link", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 1, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Course", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Course", 
-   "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, 
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fieldname": "course",
+   "fieldtype": "Link",
+   "hidden": 0,
+   "ignore_user_permissions": 0,
+   "ignore_xss_filter": 0,
+   "in_filter": 0,
+   "in_global_search": 1,
+   "in_list_view": 0,
+   "in_standard_filter": 0,
+   "label": "Course",
+   "length": 0,
+   "no_copy": 0,
+   "options": "Course",
+   "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
-  }, 
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "color", 
-   "fieldtype": "Color", 
-   "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": "Color", 
-   "length": 0, 
-   "no_copy": 0, 
-   "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, 
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fieldname": "color",
+   "fieldtype": "Color",
+   "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": "Color",
+   "length": 0,
+   "no_copy": 0,
+   "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
-  }, 
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "section_break_6", 
-   "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, 
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fieldname": "section_break_6",
+   "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": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "default": "Today", 
-   "fieldname": "schedule_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": "Schedule 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": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "default": "Today",
+   "fieldname": "schedule_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": "Schedule 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": 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, 
-   "fieldname": "room", 
-   "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": "Room", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Room", 
-   "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, 
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fieldname": "room",
+   "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": "Room",
+   "length": 0,
+   "no_copy": 0,
+   "options": "Room",
+   "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
-  }, 
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "column_break_9", 
-   "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, 
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fieldname": "column_break_9",
+   "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
-  }, 
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "from_time", 
-   "fieldtype": "Time", 
-   "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 Time", 
-   "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, 
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fieldname": "from_time",
+   "fieldtype": "Time",
+   "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 Time",
+   "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
-  }, 
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "to_time", 
-   "fieldtype": "Time", 
-   "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 Time", 
-   "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, 
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fieldname": "to_time",
+   "fieldtype": "Time",
+   "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 Time",
+   "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
-  }, 
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "title", 
-   "fieldtype": "Data", 
-   "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": "Title", 
-   "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, 
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fieldname": "title",
+   "fieldtype": "Data",
+   "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": "Title",
+   "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
   }
- ], 
- "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, 
- "menu_index": 0, 
- "modified": "2018-08-21 14:44:51.827225", 
- "modified_by": "Administrator", 
- "module": "Education", 
- "name": "Course Schedule", 
- "name_case": "", 
- "owner": "Administrator", 
+ ],
+ "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,
+ "menu_index": 0,
+ "modified": "2018-08-21 14:44:51.827225",
+ "modified_by": "Administrator",
+ "module": "Education",
+ "name": "Course Schedule",
+ "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": "Academics User", 
-   "set_user_permissions": 0, 
-   "share": 1, 
-   "submit": 0, 
+   "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": "Academics User",
+   "set_user_permissions": 0,
+   "share": 1,
+   "submit": 0,
    "write": 1
   }
- ], 
- "quick_entry": 0, 
- "read_only": 0, 
- "read_only_onload": 0, 
- "restrict_to_domain": "Education", 
- "show_name_in_global_search": 0, 
- "sort_field": "schedule_date", 
- "sort_order": "DESC", 
- "title_field": "title", 
- "track_changes": 0, 
- "track_seen": 0, 
+ ],
+ "quick_entry": 0,
+ "read_only": 0,
+ "read_only_onload": 0,
+ "restrict_to_domain": "Education",
+ "show_name_in_global_search": 0,
+ "sort_field": "schedule_date",
+ "sort_order": "DESC",
+ "title_field": "title",
+ "track_changes": 0,
+ "track_seen": 0,
  "track_views": 0
 }
\ No newline at end of file
diff --git a/erpnext/education/doctype/course_schedule/course_schedule_dashboard.py b/erpnext/education/doctype/course_schedule/course_schedule_dashboard.py
new file mode 100644
index 0000000..0866cd6
--- /dev/null
+++ b/erpnext/education/doctype/course_schedule/course_schedule_dashboard.py
@@ -0,0 +1,15 @@
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
+# License: GNU General Public License v3. See license.txt
+from __future__ import unicode_literals
+from frappe import _
+
+def get_data():
+	return {
+		'fieldname': 'course_schedule',
+		'transactions': [
+			{
+				'label': _('Attendance'),
+				'items': ['Student Attendance']
+			}
+		]
+	}
\ No newline at end of file
diff --git a/erpnext/education/doctype/fee_schedule/fee_schedule.js b/erpnext/education/doctype/fee_schedule/fee_schedule.js
index 1338331..75dd446 100644
--- a/erpnext/education/doctype/fee_schedule/fee_schedule.js
+++ b/erpnext/education/doctype/fee_schedule/fee_schedule.js
@@ -3,13 +3,13 @@
 
 frappe.ui.form.on('Fee Schedule', {
 	setup: function(frm) {
-		frm.add_fetch("fee_structure", "receivable_account", "receivable_account");
-		frm.add_fetch("fee_structure", "income_account", "income_account");
-		frm.add_fetch("fee_structure", "cost_center", "cost_center");
+		frm.add_fetch('fee_structure', 'receivable_account', 'receivable_account');
+		frm.add_fetch('fee_structure', 'income_account', 'income_account');
+		frm.add_fetch('fee_structure', 'cost_center', 'cost_center');
 	},
 
 	onload: function(frm) {
-		frm.set_query("receivable_account", function(doc) {
+		frm.set_query('receivable_account', function(doc) {
 			return {
 				filters: {
 					'account_type': 'Receivable',
@@ -18,7 +18,8 @@
 				}
 			};
 		});
-		frm.set_query("income_account", function(doc) {
+
+		frm.set_query('income_account', function(doc) {
 			return {
 				filters: {
 					'account_type': 'Income Account',
@@ -27,57 +28,59 @@
 				}
 			};
 		});
-		frm.set_query("student_group", "student_groups", function() {
+
+		frm.set_query('student_group', 'student_groups', function() {
 			return {
-				"program": frm.doc.program,
-				"academic_term": frm.doc.academic_term,
-				"academic_year": frm.doc.academic_year,
-				"disabled": 0
+				'program': frm.doc.program,
+				'academic_term': frm.doc.academic_term,
+				'academic_year': frm.doc.academic_year,
+				'disabled': 0
 			};
 		});
-		frappe.realtime.on("fee_schedule_progress", function(data) {
+
+		frappe.realtime.on('fee_schedule_progress', function(data) {
 			if (data.reload && data.reload === 1) {
 				frm.reload_doc();
 			}
 			if (data.progress) {
-				let progress_bar = $(cur_frm.dashboard.progress_area).find(".progress-bar");
+				let progress_bar = $(cur_frm.dashboard.progress_area).find('.progress-bar');
 				if (progress_bar) {
-					$(progress_bar).removeClass("progress-bar-danger").addClass("progress-bar-success progress-bar-striped");
-					$(progress_bar).css("width", data.progress+"%");
+					$(progress_bar).removeClass('progress-bar-danger').addClass('progress-bar-success progress-bar-striped');
+					$(progress_bar).css('width', data.progress+'%');
 				}
 			}
 		});
 	},
 
 	refresh: function(frm) {
-		if(!frm.doc.__islocal && frm.doc.__onload && frm.doc.__onload.dashboard_info &&
-			frm.doc.fee_creation_status=="Successful") {
+		if (!frm.doc.__islocal && frm.doc.__onload && frm.doc.__onload.dashboard_info &&
+			frm.doc.fee_creation_status === 'Successful') {
 			var info = frm.doc.__onload.dashboard_info;
 			frm.dashboard.add_indicator(__('Total Collected: {0}', [format_currency(info.total_paid,
 				info.currency)]), 'blue');
 			frm.dashboard.add_indicator(__('Total Outstanding: {0}', [format_currency(info.total_unpaid,
 				info.currency)]), info.total_unpaid ? 'orange' : 'green');
 		}
-		if (frm.doc.fee_creation_status=="In Process") {
-			frm.dashboard.add_progress("Fee Creation Status", "0");
+		if (frm.doc.fee_creation_status === 'In Process') {
+			frm.dashboard.add_progress('Fee Creation Status', '0');
 		}
-		if (frm.doc.docstatus==1 && !frm.doc.fee_creation_status || frm.doc.fee_creation_status == "Failed") {
+		if (frm.doc.docstatus === 1 && !frm.doc.fee_creation_status || frm.doc.fee_creation_status === 'Failed') {
 			frm.add_custom_button(__('Create Fees'), function() {
 				frappe.call({
-					method: "create_fees",
+					method: 'create_fees',
 					doc: frm.doc,
 					callback: function() {
 						frm.refresh();
 					}
 				});
-			}, "fa fa-play", "btn-success");
+			}).addClass('btn-primary');;
 		}
-		if (frm.doc.fee_creation_status == "Successful") {
-			frm.add_custom_button(__("View Fees Records"), function() {
+		if (frm.doc.fee_creation_status === 'Successful') {
+			frm.add_custom_button(__('View Fees Records'), function() {
 				frappe.route_options = {
 					fee_schedule: frm.doc.name
 				};
-				frappe.set_route("List", "Fees");
+				frappe.set_route('List', 'Fees');
 			});
 		}
 
@@ -86,35 +89,35 @@
 	fee_structure: function(frm) {
 		if (frm.doc.fee_structure) {
 			frappe.call({
-				method: "erpnext.education.doctype.fee_schedule.fee_schedule.get_fee_structure",
+				method: 'erpnext.education.doctype.fee_schedule.fee_schedule.get_fee_structure',
 				args: {
-					"target_doc": frm.doc.name,
-					"source_name": frm.doc.fee_structure
+					'target_doc': frm.doc.name,
+					'source_name': frm.doc.fee_structure
 				},
 				callback: function(r) {
 					var doc = frappe.model.sync(r.message);
-					frappe.set_route("Form", doc[0].doctype, doc[0].name);
+					frappe.set_route('Form', doc[0].doctype, doc[0].name);
 				}
 			});
 		}
 	}
 });
 
-frappe.ui.form.on("Fee Schedule Student Group", {
+frappe.ui.form.on('Fee Schedule Student Group', {
 	student_group: function(frm, cdt, cdn) {
 		var row = locals[cdt][cdn];
 		if (row.student_group && frm.doc.academic_year) {
 			frappe.call({
-				method: "erpnext.education.doctype.fee_schedule.fee_schedule.get_total_students",
+				method: 'erpnext.education.doctype.fee_schedule.fee_schedule.get_total_students',
 				args: {
-					"student_group": row.student_group,
-					"academic_year": frm.doc.academic_year,
-					"academic_term": frm.doc.academic_term,
-					"student_category": frm.doc.student_category
+					'student_group': row.student_group,
+					'academic_year': frm.doc.academic_year,
+					'academic_term': frm.doc.academic_term,
+					'student_category': frm.doc.student_category
 				},
 				callback: function(r) {
-					if(!r.exc) {
-						frappe.model.set_value(cdt, cdn, "total_students", r.message);
+					if (!r.exc) {
+						frappe.model.set_value(cdt, cdn, 'total_students', r.message);
 					}
 				}
 			});
diff --git a/erpnext/education/doctype/fee_schedule/fee_schedule.json b/erpnext/education/doctype/fee_schedule/fee_schedule.json
index 7918318..23b3212 100644
--- a/erpnext/education/doctype/fee_schedule/fee_schedule.json
+++ b/erpnext/education/doctype/fee_schedule/fee_schedule.json
@@ -168,6 +168,7 @@
    "fieldname": "grand_total_in_words",
    "fieldtype": "Data",
    "label": "In Words",
+   "length": 240,
    "read_only": 1
   },
   {
@@ -272,7 +273,7 @@
  ],
  "is_submittable": 1,
  "links": [],
- "modified": "2020-05-15 08:39:20.682837",
+ "modified": "2020-07-18 05:11:49.905457",
  "modified_by": "Administrator",
  "module": "Education",
  "name": "Fee Schedule",
diff --git a/erpnext/education/doctype/fee_schedule/fee_schedule_dashboard.py b/erpnext/education/doctype/fee_schedule/fee_schedule_dashboard.py
new file mode 100644
index 0000000..acfe400
--- /dev/null
+++ b/erpnext/education/doctype/fee_schedule/fee_schedule_dashboard.py
@@ -0,0 +1,13 @@
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
+# License: GNU General Public License v3. See license.txt
+from __future__ import unicode_literals
+
+def get_data():
+	return {
+		'fieldname': 'fee_schedule',
+		'transactions': [
+			{
+				'items': ['Fees']
+			}
+		]
+	}
\ No newline at end of file
diff --git a/erpnext/education/doctype/fee_structure/fee_structure.js b/erpnext/education/doctype/fee_structure/fee_structure.js
index f09d2ef..b331c6d 100644
--- a/erpnext/education/doctype/fee_structure/fee_structure.js
+++ b/erpnext/education/doctype/fee_structure/fee_structure.js
@@ -3,21 +3,21 @@
 
 frappe.ui.form.on('Fee Structure', {
 	setup: function(frm) {
-		frm.add_fetch("company", "default_receivable_account", "receivable_account");
-		frm.add_fetch("company", "default_income_account", "income_account");
-		frm.add_fetch("company", "cost_center", "cost_center");
+		frm.add_fetch('company', 'default_receivable_account', 'receivable_account');
+		frm.add_fetch('company', 'default_income_account', 'income_account');
+		frm.add_fetch('company', 'cost_center', 'cost_center');
 	},
 
 	onload: function(frm) {
-		frm.set_query("academic_term", function() {
+		frm.set_query('academic_term', function() {
 			return {
-				"filters": {
-					"academic_year": frm.doc.academic_year
+				'filters': {
+					'academic_year': frm.doc.academic_year
 				}
 			};
 		});
 
-		frm.set_query("receivable_account", function(doc) {
+		frm.set_query('receivable_account', function(doc) {
 			return {
 				filters: {
 					'account_type': 'Receivable',
@@ -26,7 +26,7 @@
 				}
 			};
 		});
-		frm.set_query("income_account", function(doc) {
+		frm.set_query('income_account', function(doc) {
 			return {
 				filters: {
 					'account_type': 'Income Account',
@@ -38,27 +38,27 @@
 	},
 
 	refresh: function(frm) {
-		if(frm.doc.docstatus === 1) {
+		if (frm.doc.docstatus === 1) {
 			frm.add_custom_button(__('Create Fee Schedule'), function() {
 				frm.events.make_fee_schedule(frm);
-			});
+			}).addClass('btn-primary');
 		}
 	},
 
 	make_fee_schedule: function(frm) {
 		frappe.model.open_mapped_doc({
-			method: "erpnext.education.doctype.fee_structure.fee_structure.make_fee_schedule",
+			method: 'erpnext.education.doctype.fee_structure.fee_structure.make_fee_schedule',
 			frm: frm
 		});
 	}
 });
 
-frappe.ui.form.on("Fee Component", {
+frappe.ui.form.on('Fee Component', {
 	amount: function(frm) {
 		var total_amount = 0;
-		for(var i=0;i<frm.doc.components.length;i++) {
+		for (var i=0;i<frm.doc.components.length;i++) {
 			total_amount += frm.doc.components[i].amount;
 		}
-		frm.set_value("total_amount", total_amount);
+		frm.set_value('total_amount', total_amount);
 	}
 });
\ No newline at end of file
diff --git a/erpnext/education/doctype/fee_structure/fee_structure_dashboard.py b/erpnext/education/doctype/fee_structure/fee_structure_dashboard.py
new file mode 100644
index 0000000..73e314f
--- /dev/null
+++ b/erpnext/education/doctype/fee_structure/fee_structure_dashboard.py
@@ -0,0 +1,15 @@
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
+# License: GNU General Public License v3. See license.txt
+from __future__ import unicode_literals
+from frappe import _
+
+def get_data():
+	return {
+		'fieldname': 'fee_structure',
+		'transactions': [
+			{
+                'label': _('Fee'),
+				'items': ['Fees', 'Fee Schedule']
+			}
+		]
+	}
\ No newline at end of file
diff --git a/erpnext/education/doctype/fees/fees.js b/erpnext/education/doctype/fees/fees.js
index 17ef449..867866f 100644
--- a/erpnext/education/doctype/fees/fees.js
+++ b/erpnext/education/doctype/fees/fees.js
@@ -55,14 +55,15 @@
 			frm.set_df_property('posting_date', 'read_only', 1);
 			frm.set_df_property('posting_time', 'read_only', 1);
 		}
-		if(frm.doc.docstatus===1) {
+		if(frm.doc.docstatus > 0) {
 			frm.add_custom_button(__('Accounting Ledger'), function() {
 				frappe.route_options = {
 					voucher_no: frm.doc.name,
 					from_date: frm.doc.posting_date,
-					to_date: frm.doc.posting_date,
+					to_date: moment(frm.doc.modified).format('YYYY-MM-DD'),
 					company: frm.doc.company,
-					group_by_voucher: false
+					group_by: '',
+					show_cancelled_entries: frm.doc.docstatus === 2
 				};
 				frappe.set_route("query-report", "General Ledger");
 			}, __("View"));
diff --git a/erpnext/education/doctype/fees/fees.json b/erpnext/education/doctype/fees/fees.json
index 676ff30..99f9f4f 100644
--- a/erpnext/education/doctype/fees/fees.json
+++ b/erpnext/education/doctype/fees/fees.json
@@ -1,4 +1,5 @@
 {
+ "actions": [],
  "allow_import": 1,
  "autoname": "naming_series:",
  "creation": "2015-09-22 16:57:22.143710",
@@ -253,6 +254,7 @@
    "fieldname": "grand_total_in_words",
    "fieldtype": "Data",
    "label": "In Words",
+   "length": 240,
    "read_only": 1
   },
   {
@@ -336,7 +338,8 @@
   }
  ],
  "is_submittable": 1,
- "modified": "2019-05-25 22:58:20.026368",
+ "links": [],
+ "modified": "2020-07-18 05:00:00.621010",
  "modified_by": "Administrator",
  "module": "Education",
  "name": "Fees",
diff --git a/erpnext/education/doctype/grading_scale/grading_scale_dashboard.py b/erpnext/education/doctype/grading_scale/grading_scale_dashboard.py
new file mode 100644
index 0000000..2a3f13b
--- /dev/null
+++ b/erpnext/education/doctype/grading_scale/grading_scale_dashboard.py
@@ -0,0 +1,20 @@
+from __future__ import unicode_literals
+from frappe import _
+
+def get_data():
+	return {
+		'fieldname': 'grading_scale',
+		'non_standard_fieldnames': {
+			'Course': 'default_grading_scale'
+		},
+		'transactions': [
+			{
+				'label': _('Course'),
+				'items': ['Course']
+			},
+			{
+				'label': _('Assessment'),
+				'items': ['Assessment Plan', 'Assessment Result']
+			}
+		]
+	}
diff --git a/erpnext/education/doctype/instructor/instructor.js b/erpnext/education/doctype/instructor/instructor.js
index 69bd2cf..abb47ed 100644
--- a/erpnext/education/doctype/instructor/instructor.js
+++ b/erpnext/education/doctype/instructor/instructor.js
@@ -3,8 +3,8 @@
 
 frappe.ui.form.on("Instructor", {
 	employee: function(frm) {
-		if(!frm.doc.employee) return;
-		frappe.db.get_value('Employee', {name: frm.doc.employee}, 'company', (d) => {
+		if (!frm.doc.employee) return;
+		frappe.db.get_value("Employee", {name: frm.doc.employee}, "company", (d) => {
 			frm.set_query("department", function() {
 				return {
 					"filters": {
@@ -22,30 +22,16 @@
 		});
 	},
 	refresh: function(frm) {
-		if(!frm.doc.__islocal) {
-			frm.add_custom_button(__("Student Group"), function() {
-				frappe.route_options = {
-					instructor: frm.doc.name
-				}
-				frappe.set_route("List", "Student Group");
-			});
-			frm.add_custom_button(__("Course Schedule"), function() {
-				frappe.route_options = {
-					instructor: frm.doc.name
-				}
-				frappe.set_route("List", "Course Schedule");
-			});
+		if (!frm.doc.__islocal) {
 			frm.add_custom_button(__("As Examiner"), function() {
-				frappe.route_options = {
+				frappe.new_doc("Assessment Plan", {
 					examiner: frm.doc.name
-				}
-				frappe.set_route("List", "Assessment Plan");
+				});
 			}, __("Assessment Plan"));
 			frm.add_custom_button(__("As Supervisor"), function() {
-				frappe.route_options = {
+				frappe.new_doc("Assessment Plan", {
 					supervisor: frm.doc.name
-				}
-				frappe.set_route("List", "Assessment Plan");
+				});
 			}, __("Assessment Plan"));
 		}
 		frm.set_query("employee", function(doc) {
diff --git a/erpnext/education/doctype/instructor/instructor.py b/erpnext/education/doctype/instructor/instructor.py
index 28df2fc..b1bfcbb 100644
--- a/erpnext/education/doctype/instructor/instructor.py
+++ b/erpnext/education/doctype/instructor/instructor.py
@@ -30,4 +30,14 @@
 		if self.employee and frappe.db.get_value("Instructor", {'employee': self.employee, 'name': ['!=', self.name]}, 'name'):
 			frappe.throw(_("Employee ID is linked with another instructor"))
 
-
+def get_timeline_data(doctype, name):
+	"""Return timeline for course schedule"""
+	return dict(frappe.db.sql(
+		"""
+			SELECT unix_timestamp(`schedule_date`), count(*)
+			FROM `tabCourse Schedule`
+			WHERE
+				instructor=%s and
+				`schedule_date` > date_sub(curdate(), interval 1 year)
+			GROUP BY schedule_date
+		""", name))
diff --git a/erpnext/education/doctype/instructor/instructor_dashboard.py b/erpnext/education/doctype/instructor/instructor_dashboard.py
new file mode 100644
index 0000000..a404fc5
--- /dev/null
+++ b/erpnext/education/doctype/instructor/instructor_dashboard.py
@@ -0,0 +1,24 @@
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
+# License: GNU General Public License v3. See license.txt
+from __future__ import unicode_literals
+from frappe import _
+
+def get_data():
+	return {
+		'heatmap': True,
+		'heatmap_message': _('This is based on the course schedules of this Instructor'),
+		'fieldname': 'instructor',
+		'non_standard_fieldnames': {
+			'Assessment Plan': 'supervisor'
+		},
+		'transactions': [
+			{
+				'label': _('Course and Assessment'),
+				'items': ['Course Schedule', 'Assessment Plan']
+			},
+			{
+				'label': _('Students'),
+				'items': ['Student Group']
+			}
+		]
+	}
\ No newline at end of file
diff --git a/erpnext/education/doctype/program/program_dashboard.py b/erpnext/education/doctype/program/program_dashboard.py
index cb8f742..c5d2494 100644
--- a/erpnext/education/doctype/program/program_dashboard.py
+++ b/erpnext/education/doctype/program/program_dashboard.py
@@ -10,11 +10,15 @@
 			},
 			{
 				'label': _('Student Activity'),
-				'items': ['Student Group' ]
+				'items': ['Student Group', 'Student Log']
 			},
 			{
 				'label': _('Fee'),
-				'items': ['Fees','Fee Structure']
+				'items': ['Fees','Fee Structure', 'Fee Schedule']
+			},
+			{
+				'label': _('Assessment'),
+				'items': ['Assessment Plan', 'Assessment Result']
 			}
 		]
 	}
\ No newline at end of file
diff --git a/erpnext/education/doctype/program_enrollment/program_enrollment_dashboard.py b/erpnext/education/doctype/program_enrollment/program_enrollment_dashboard.py
new file mode 100644
index 0000000..18d307c
--- /dev/null
+++ b/erpnext/education/doctype/program_enrollment/program_enrollment_dashboard.py
@@ -0,0 +1,19 @@
+from __future__ import unicode_literals
+from frappe import _
+
+def get_data():
+	return {
+		'fieldname': 'program_enrollment',
+		'transactions': [
+			{
+				'label': _('Course and Fee'),
+				'items': ['Course Enrollment', 'Fees']
+			}
+		],
+		'reports': [
+			{
+				'label': _('Report'),
+				'items': ['Student and Guardian Contact Details']
+			}
+		]
+	}
\ No newline at end of file
diff --git a/erpnext/education/doctype/quiz/quiz.js b/erpnext/education/doctype/quiz/quiz.js
index 7b87088..01bcf73 100644
--- a/erpnext/education/doctype/quiz/quiz.js
+++ b/erpnext/education/doctype/quiz/quiz.js
@@ -3,11 +3,17 @@
 
 frappe.ui.form.on('Quiz', {
 	refresh: function(frm) {
-
+		if (!frm.doc.__islocal) {
+			frm.add_custom_button(__('Add to Topics'), function() {
+				frm.trigger('add_quiz_to_topics');
+			}, __('Action'));
+		}
 	},
+
 	validate: function(frm){
 		frm.events.check_duplicate_question(frm.doc.question);
 	},
+
 	check_duplicate_question: function(questions_data){
 		var questions = [];
 		questions_data.forEach(function(q){
@@ -15,7 +21,51 @@
 		});
 		var questions_set = new Set(questions);
 		if (questions.length != questions_set.size) {
-			frappe.throw(__("The question cannot be duplicate"));
+			frappe.throw(__('The question cannot be duplicate'));
 		}
+	},
+
+	add_quiz_to_topics: function(frm) {
+		get_topics_without_quiz(frm.doc.name).then(r => {
+			if (r.message.length) {
+				frappe.prompt([
+					{
+						fieldname: 'topics',
+						label: __('Topics'),
+						fieldtype: 'MultiSelectPills',
+						get_data: function() {
+							return r.message;
+						}
+					}
+				],
+				function(data) {
+					frappe.call({
+						method: 'erpnext.education.doctype.topic.topic.add_content_to_topics',
+						args: {
+							'content_type': 'Quiz',
+							'content': frm.doc.name,
+							'topics': data.topics,
+						},
+						callback: function(r) {
+							if (!r.exc) {
+								frm.reload_doc();
+							}
+						},
+						freeze: true,
+						freeze_message: __('...Adding Quiz to Topics')
+					});
+				}, __('Add Quiz to Topics'), __('Add'));
+			} else {
+				frappe.msgprint(__('This quiz is already added to the existing topics'));
+			}
+		});
 	}
-});
\ No newline at end of file
+});
+
+let get_topics_without_quiz = function(quiz) {
+	return frappe.call({
+		type: 'GET',
+		method: 'erpnext.education.doctype.quiz.quiz.get_topics_without_quiz',
+		args: {'quiz': quiz}
+	});
+};
\ No newline at end of file
diff --git a/erpnext/education/doctype/quiz/quiz.py b/erpnext/education/doctype/quiz/quiz.py
index ae1cb6c..a774b88 100644
--- a/erpnext/education/doctype/quiz/quiz.py
+++ b/erpnext/education/doctype/quiz/quiz.py
@@ -4,6 +4,7 @@
 
 from __future__ import unicode_literals
 import frappe
+import json
 from frappe import _
 from frappe.model.document import Document
 
@@ -59,3 +60,12 @@
 	except TypeError:
 		frappe.throw(_("Compare List function takes on list arguments"))
 
+@frappe.whitelist()
+def get_topics_without_quiz(quiz):
+	data = []
+	for entry in frappe.db.get_all('Topic'):
+		topic = frappe.get_doc('Topic', entry.name)
+		topic_contents = [tc.content for tc in topic.topic_content]
+		if not topic_contents or quiz not in topic_contents:
+			data.append(topic.name)
+	return data
\ No newline at end of file
diff --git a/erpnext/education/doctype/room/room.js b/erpnext/education/doctype/room/room.js
index 032db98..20cee6b 100644
--- a/erpnext/education/doctype/room/room.js
+++ b/erpnext/education/doctype/room/room.js
@@ -1,10 +1,2 @@
-frappe.ui.form.on("Room", "refresh", function(frm) {
-	if(!cur_frm.doc.__islocal) {
-		frm.add_custom_button(__("Course Schedule"), function() {
-			frappe.route_options = {
-				room: frm.doc.name
-			}
-			frappe.set_route("List", "Course Schedule");
-		});
-	}
+frappe.ui.form.on("Room", {
 });
\ No newline at end of file
diff --git a/erpnext/education/doctype/room/room_dashboard.py b/erpnext/education/doctype/room/room_dashboard.py
new file mode 100644
index 0000000..99aac33
--- /dev/null
+++ b/erpnext/education/doctype/room/room_dashboard.py
@@ -0,0 +1,19 @@
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
+# License: GNU General Public License v3. See license.txt
+from __future__ import unicode_literals
+from frappe import _
+
+def get_data():
+	return {
+		'fieldname': 'room',
+		'transactions': [
+			{
+				'label': _('Course'),
+				'items': ['Course Schedule']
+			},
+			{
+				'label': _('Assessment'),
+				'items': ['Assessment Plan']
+			}
+		]
+	}
\ No newline at end of file
diff --git a/erpnext/education/doctype/student/student.py b/erpnext/education/doctype/student/student.py
index 6b545d9..e0d7514 100644
--- a/erpnext/education/doctype/student/student.py
+++ b/erpnext/education/doctype/student/student.py
@@ -25,7 +25,7 @@
 		for sibling in self.siblings:
 			if sibling.date_of_birth and getdate(sibling.date_of_birth) > getdate():
 				frappe.throw(_("Row {0}:Sibling Date of Birth cannot be greater than today.").format(sibling.idx))
-				
+
 		if self.date_of_birth and getdate(self.date_of_birth) >= getdate(today()):
 			frappe.throw(_("Date of Birth cannot be greater than today."))
 
@@ -157,5 +157,5 @@
 		from `tabStudent Attendance` where
 			student=%s
 			and `date` > date_sub(curdate(), interval 1 year)
-			and status = 'Present'
+			and docstatus = 1 and status = 'Present'
 			group by date''', name))
diff --git a/erpnext/education/doctype/student_attendance/student_attendance.json b/erpnext/education/doctype/student_attendance/student_attendance.json
index 23e10e6..55384b9 100644
--- a/erpnext/education/doctype/student_attendance/student_attendance.json
+++ b/erpnext/education/doctype/student_attendance/student_attendance.json
@@ -1,287 +1,125 @@
 {
- "allow_copy": 0, 
- "allow_guest_to_view": 0, 
- "allow_import": 1, 
- "allow_rename": 0, 
- "autoname": "", 
- "beta": 0, 
- "creation": "2015-11-05 15:20:23.045996", 
- "custom": 0, 
- "docstatus": 0, 
- "doctype": "DocType", 
- "document_type": "Document", 
- "editable_grid": 0, 
- "engine": "InnoDB", 
+ "actions": [],
+ "allow_import": 1,
+ "autoname": "naming_series:",
+ "creation": "2015-11-05 15:20:23.045996",
+ "doctype": "DocType",
+ "document_type": "Document",
+ "engine": "InnoDB",
+ "field_order": [
+  "naming_series",
+  "student",
+  "student_name",
+  "course_schedule",
+  "student_group",
+  "column_break_3",
+  "date",
+  "status",
+  "leave_application",
+  "amended_from"
+ ],
  "fields": [
   {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "student", 
-   "fieldtype": "Link", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 1, 
-   "in_list_view": 0, 
-   "in_standard_filter": 1, 
-   "label": "Student", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Student", 
-   "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": 1, 
-   "set_only_once": 0, 
-   "translatable": 0,
-   "unique": 0
-  }, 
+   "fieldname": "student",
+   "fieldtype": "Link",
+   "in_global_search": 1,
+   "in_standard_filter": 1,
+   "label": "Student",
+   "options": "Student",
+   "reqd": 1,
+   "search_index": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "course_schedule", 
-   "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": "Course Schedule", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Course Schedule", 
-   "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": "course_schedule",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "label": "Course Schedule",
+   "options": "Course Schedule"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "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": "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": 1, 
-   "set_only_once": 0, 
-   "translatable": 0,
-   "unique": 0
-  }, 
+   "fieldname": "date",
+   "fieldtype": "Date",
+   "label": "Date",
+   "reqd": 1,
+   "search_index": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "column_break_3", 
-   "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_3",
+   "fieldtype": "Column Break"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
    "fetch_from": "student.title",
-   "fieldname": "student_name", 
-   "fieldtype": "Read Only", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 1, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Student Name", 
-   "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
-  }, 
+   "fieldname": "student_name",
+   "fieldtype": "Read Only",
+   "in_global_search": 1,
+   "label": "Student Name"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "student_group", 
-   "fieldtype": "Link", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 1, 
-   "in_list_view": 0, 
-   "in_standard_filter": 1, 
-   "label": "Student Group", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Student Group", 
-   "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": "student_group",
+   "fieldtype": "Link",
+   "in_global_search": 1,
+   "in_standard_filter": 1,
+   "label": "Student Group",
+   "options": "Student Group"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "default": "Present", 
-   "fieldname": "status", 
-   "fieldtype": "Select", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 1, 
-   "label": "Status", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Present\nAbsent", 
-   "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
+   "default": "Present",
+   "fieldname": "status",
+   "fieldtype": "Select",
+   "in_list_view": 1,
+   "in_standard_filter": 1,
+   "label": "Status",
+   "options": "Present\nAbsent",
+   "reqd": 1
+  },
+  {
+   "fieldname": "leave_application",
+   "fieldtype": "Link",
+   "label": "Leave Application",
+   "options": "Student Leave Application",
+   "read_only": 1
+  },
+  {
+   "fieldname": "naming_series",
+   "fieldtype": "Select",
+   "label": "Series",
+   "options": "EDU-ATT-.YYYY.-"
+  },
+  {
+   "fieldname": "amended_from",
+   "fieldtype": "Link",
+   "label": "Amended From",
+   "no_copy": 1,
+   "options": "Student Attendance",
+   "print_hide": 1,
+   "read_only": 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-07-27 10:48:22.301531", 
- "modified_by": "Administrator", 
- "module": "Education", 
- "name": "Student Attendance", 
- "name_case": "", 
- "owner": "Administrator", 
+ ],
+ "is_submittable": 1,
+ "links": [],
+ "modified": "2020-07-08 13:55:42.580181",
+ "modified_by": "Administrator",
+ "module": "Education",
+ "name": "Student Attendance",
+ "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": "Academics User", 
-   "set_user_permissions": 0, 
-   "share": 1, 
-   "submit": 0, 
+   "cancel": 1,
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "export": 1,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "Academics User",
+   "share": 1,
+   "submit": 1,
    "write": 1
   }
- ], 
- "quick_entry": 0, 
- "read_only": 0, 
- "read_only_onload": 0, 
- "restrict_to_domain": "Education", 
- "show_name_in_global_search": 0, 
- "sort_field": "modified", 
- "sort_order": "DESC", 
- "title_field": "student_name", 
- "track_changes": 0, 
- "track_seen": 0
+ ],
+ "restrict_to_domain": "Education",
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "title_field": "student_name"
 }
\ No newline at end of file
diff --git a/erpnext/education/doctype/student_attendance/student_attendance.py b/erpnext/education/doctype/student_attendance/student_attendance.py
index 06ac4fb..c1b6850 100644
--- a/erpnext/education/doctype/student_attendance/student_attendance.py
+++ b/erpnext/education/doctype/student_attendance/student_attendance.py
@@ -6,52 +6,63 @@
 import frappe
 from frappe.model.document import Document
 from frappe import _
-from frappe.utils import cstr
+from frappe.utils import get_link_to_form
 from erpnext.education.api import get_student_group_students
 
 
 class StudentAttendance(Document):
 	def validate(self):
-		self.validate_date()
 		self.validate_mandatory()
-		self.validate_course_schedule()
+		self.set_date()
+		self.set_student_group()
 		self.validate_student()
 		self.validate_duplication()
-		
-	def validate_date(self):
+
+	def set_date(self):
 		if self.course_schedule:
-			self.date = frappe.db.get_value("Course Schedule", self.course_schedule, "schedule_date")
-	
+			self.date = frappe.db.get_value('Course Schedule', self.course_schedule, 'schedule_date')
+
 	def validate_mandatory(self):
 		if not (self.student_group or self.course_schedule):
-			frappe.throw(_("""Student Group or Course Schedule is mandatory"""))
-	
-	def validate_course_schedule(self):
+			frappe.throw(_('{0} or {1} is mandatory').format(frappe.bold('Student Group'),
+				frappe.bold('Course Schedule')), title=_('Mandatory Fields'))
+
+	def set_student_group(self):
 		if self.course_schedule:
-			self.student_group = frappe.db.get_value("Course Schedule", self.course_schedule, "student_group")
-	
+			self.student_group = frappe.db.get_value('Course Schedule', self.course_schedule, 'student_group')
+
 	def validate_student(self):
 		if self.course_schedule:
-			student_group = frappe.db.get_value("Course Schedule", self.course_schedule, "student_group")
+			student_group = frappe.db.get_value('Course Schedule', self.course_schedule, 'student_group')
 		else:
 			student_group = self.student_group
 		student_group_students = [d.student for d in get_student_group_students(student_group)]
 		if student_group and self.student not in student_group_students:
-			frappe.throw(_('''Student {0}: {1} does not belong to Student Group {2}'''.format(self.student, self.student_name, student_group)))
+			student_group_doc = get_link_to_form('Student Group', student_group)
+			frappe.throw(_('Student {0}: {1} does not belong to Student Group {2}').format(
+				frappe.bold(self.student), self.student_name, frappe.bold(student_group_doc)))
 
 	def validate_duplication(self):
 		"""Check if the Attendance Record is Unique"""
-		attendance_records=None
+		attendance_record = None
 		if self.course_schedule:
-			attendance_records= frappe.db.sql("""select name from `tabStudent Attendance` where \
-				student= %s and ifnull(course_schedule, '')= %s and name != %s""",
-				(self.student, cstr(self.course_schedule), self.name))
+			attendance_record = frappe.db.exists('Student Attendance', {
+				'student': self.student,
+				'course_schedule': self.course_schedule,
+				'docstatus': ('!=', 2),
+				'name': ('!=', self.name)
+			})
 		else:
-			attendance_records= frappe.db.sql("""select name from `tabStudent Attendance` where \
-				student= %s and student_group= %s and date= %s and name != %s and \
-				(course_schedule is Null or course_schedule='')""",
-				(self.student, self.student_group, self.date, self.name))
-			
-		if attendance_records:
-			frappe.throw(_("Attendance Record {0} exists against Student {1}")
-				.format(attendance_records[0][0], self.student))
+			attendance_record = frappe.db.exists('Student Attendance', {
+				'student': self.student,
+				'student_group': self.student_group,
+				'date': self.date,
+				'docstatus': ('!=', 2),
+				'name': ('!=', self.name),
+				'course_schedule': ''
+			})
+
+		if attendance_record:
+			record = get_link_to_form('Attendance Record', attendance_record)
+			frappe.throw(_('Student Attendance record {0} already exists against the Student {1}')
+				.format(record, frappe.bold(self.student)), title=_('Duplicate Entry'))
diff --git a/erpnext/education/doctype/student_attendance/student_attendance_dashboard.py b/erpnext/education/doctype/student_attendance/student_attendance_dashboard.py
new file mode 100644
index 0000000..9c41b8f
--- /dev/null
+++ b/erpnext/education/doctype/student_attendance/student_attendance_dashboard.py
@@ -0,0 +1,12 @@
+from __future__ import unicode_literals
+from frappe import _
+
+def get_data():
+	return {
+		'reports': [
+			{
+				'label': _('Reports'),
+				'items': ['Student Monthly Attendance Sheet', 'Student Batch-Wise Attendance']
+			}
+		]
+	}
\ No newline at end of file
diff --git a/erpnext/education/doctype/student_category/student_category_dashboard.py b/erpnext/education/doctype/student_category/student_category_dashboard.py
new file mode 100644
index 0000000..f31c34b
--- /dev/null
+++ b/erpnext/education/doctype/student_category/student_category_dashboard.py
@@ -0,0 +1,13 @@
+from __future__ import unicode_literals
+from frappe import _
+
+def get_data():
+	return {
+		'fieldname': 'student_category',
+		'transactions': [
+			{
+				'label': _('Fee'),
+				'items': ['Fee Structure', 'Fee Schedule', 'Fees']
+			}
+		]
+	}
diff --git a/erpnext/education/doctype/student_group/student_group.js b/erpnext/education/doctype/student_group/student_group.js
index 1372440..51e3b74 100644
--- a/erpnext/education/doctype/student_group/student_group.js
+++ b/erpnext/education/doctype/student_group/student_group.js
@@ -1,18 +1,18 @@
-cur_frm.add_fetch("student", "title", "student_name");
+cur_frm.add_fetch('student', 'title', 'student_name');
 
-frappe.ui.form.on("Student Group", {
+frappe.ui.form.on('Student Group', {
 	onload: function(frm) {
-		frm.set_query("academic_term", function() {
+		frm.set_query('academic_term', function() {
 			return {
-				"filters": {
-					"academic_year": (frm.doc.academic_year)
+				filters: {
+					'academic_year': (frm.doc.academic_year)
 				}
 			};
 		});
 		if (!frm.__islocal) {
-			frm.set_query("student", "students", function() {
+			frm.set_query('student', 'students', function() {
 				return{
-					query: "erpnext.education.doctype.student_group.student_group.fetch_students",
+					query: 'erpnext.education.doctype.student_group.student_group.fetch_students',
 					filters: {
 						'academic_year': frm.doc.academic_year,
 						'group_based_on': frm.doc.group_based_on,
@@ -30,87 +30,86 @@
 
 	refresh: function(frm) {
 		if (!frm.doc.__islocal) {
-			frm.add_custom_button(__("Attendance"), function() {
-				frappe.route_options = {
-					based_on: "Student Group",
-					student_group: frm.doc.name
-				}
-				frappe.set_route("List", "Student Attendance Tool");
-			});
-			frm.add_custom_button(__("Course Schedule"), function() {
-				frappe.route_options = {
-					student_group: frm.doc.name
-				}
-				frappe.set_route("List", "Course Schedule");
-			});
-			frm.add_custom_button(__("Assessment Plan"), function() {
-				frappe.route_options = {
-					student_group: frm.doc.name
-				}
-				frappe.set_route("List", "Assessment Plan");
-			});
-			frm.add_custom_button(__("Update Email Group"), function() {
+
+			frm.add_custom_button(__('Add Guardians to Email Group'), function() {
 				frappe.call({
-					method: "erpnext.education.api.update_email_group",
+					method: 'erpnext.education.api.update_email_group',
 					args: {
-						"doctype": "Student Group",
-						"name": frm.doc.name
+						'doctype': 'Student Group',
+						'name': frm.doc.name
 					}
 				});
-			});
-			frm.add_custom_button(__("Newsletter"), function() {
+			}, __('Actions'));
+
+			frm.add_custom_button(__('Student Attendance Tool'), function() {
 				frappe.route_options = {
-					"Newsletter Email Group.email_group": frm.doc.name
+					based_on: 'Student Group',
+					student_group: frm.doc.name
 				}
-				frappe.set_route("List", "Newsletter");
-			});
+				frappe.set_route('Form', 'Student Attendance Tool', 'Student Attendance Tool');
+			}, __('Tools'));
+
+			frm.add_custom_button(__('Course Scheduling Tool'), function() {
+				frappe.route_options = {
+					student_group: frm.doc.name
+				}
+				frappe.set_route('Form', 'Course Scheduling Tool', 'Course Scheduling Tool');
+			}, __('Tools'));
+
+			frm.add_custom_button(__('Newsletter'), function() {
+				frappe.route_options = {
+					'Newsletter Email Group.email_group': frm.doc.name
+				}
+				frappe.set_route('List', 'Newsletter');
+			}, __('View'));
+
 		}
 	},
-	
+
 	group_based_on: function(frm) {
-		if (frm.doc.group_based_on == "Batch") {
+		if (frm.doc.group_based_on == 'Batch') {
 			frm.doc.course = null;
 			frm.set_df_property('program', 'reqd', 1);
 			frm.set_df_property('course', 'reqd', 0);
 		}
-		else if (frm.doc.group_based_on == "Course") {
+		else if (frm.doc.group_based_on == 'Course') {
 			frm.set_df_property('program', 'reqd', 0);
 			frm.set_df_property('course', 'reqd', 1);
 		}
-		else if (frm.doc.group_based_on == "Activity") {
+		else if (frm.doc.group_based_on == 'Activity') {
 			frm.set_df_property('program', 'reqd', 0);
 			frm.set_df_property('course', 'reqd', 0);
 		}
 	},
 
 	get_students: function(frm) {
-		if (frm.doc.group_based_on == "Batch" || frm.doc.group_based_on == "Course") {
+		if (frm.doc.group_based_on == 'Batch' || frm.doc.group_based_on == 'Course') {
 			var student_list = [];
 			var max_roll_no = 0;
-			$.each(frm.doc.students, function(i,d) {
+			$.each(frm.doc.students, function(_i,d) {
 				student_list.push(d.student);
 				if (d.group_roll_number>max_roll_no) {
 					max_roll_no = d.group_roll_number;
 				}
 			});
 
-			if(frm.doc.academic_year) {
+			if (frm.doc.academic_year) {
 				frappe.call({
-					method: "erpnext.education.doctype.student_group.student_group.get_students",
+					method: 'erpnext.education.doctype.student_group.student_group.get_students',
 					args: {
-						"academic_year": frm.doc.academic_year,
-						"academic_term": frm.doc.academic_term,
-						"group_based_on": frm.doc.group_based_on,
-						"program": frm.doc.program,
-						"batch" : frm.doc.batch,
-						"student_category" : frm.doc.student_category,
-						"course": frm.doc.course
+						'academic_year': frm.doc.academic_year,
+						'academic_term': frm.doc.academic_term,
+						'group_based_on': frm.doc.group_based_on,
+						'program': frm.doc.program,
+						'batch' : frm.doc.batch,
+						'student_category' : frm.doc.student_category,
+						'course': frm.doc.course
 					},
 					callback: function(r) {
-						if(r.message) {
+						if (r.message) {
 							$.each(r.message, function(i, d) {
 								if(!in_list(student_list, d.student)) {
-									var s = frm.add_child("students");
+									var s = frm.add_child('students');
 									s.student = d.student;
 									s.student_name = d.student_name;
 									if (d.active === 0) {
@@ -119,16 +118,16 @@
 									s.group_roll_number = ++max_roll_no;
 								}
 							});
-							refresh_field("students");
+							refresh_field('students');
 							frm.save();
 						} else {
-							frappe.msgprint(__("Student Group is already updated."))
+							frappe.msgprint(__('Student Group is already updated.'))
 						}
 					}
 				})
 			}
 		} else {
-			frappe.msgprint(__("Select students manually for the Activity based Group"));
+			frappe.msgprint(__('Select students manually for the Activity based Group'));
 		}
 	}
 });
diff --git a/erpnext/education/doctype/student_group/student_group_dashboard.py b/erpnext/education/doctype/student_group/student_group_dashboard.py
new file mode 100644
index 0000000..ad7a6de
--- /dev/null
+++ b/erpnext/education/doctype/student_group/student_group_dashboard.py
@@ -0,0 +1,19 @@
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
+# License: GNU General Public License v3. See license.txt
+from __future__ import unicode_literals
+from frappe import _
+
+def get_data():
+	return {
+		'fieldname': 'student_group',
+		'transactions': [
+			{
+				'label': _('Assessment'),
+				'items': ['Assessment Plan', 'Assessment Result']
+			},
+			{
+				'label': _('Course'),
+				'items': ['Course Schedule']
+			}
+		]
+	}
\ No newline at end of file
diff --git a/erpnext/education/doctype/student_leave_application/student_leave_application.json b/erpnext/education/doctype/student_leave_application/student_leave_application.json
index fe38b87..ad53976 100644
--- a/erpnext/education/doctype/student_leave_application/student_leave_application.json
+++ b/erpnext/education/doctype/student_leave_application/student_leave_application.json
@@ -1,375 +1,158 @@
 {
- "allow_copy": 0, 
- "allow_guest_to_view": 0, 
- "allow_import": 0, 
- "allow_rename": 0, 
- "autoname": "EDU-SLA-.YYYY.-.#####", 
- "beta": 0, 
- "creation": "2016-11-28 15:38:54.793854", 
- "custom": 0, 
- "docstatus": 0, 
- "doctype": "DocType", 
- "document_type": "", 
- "editable_grid": 1, 
- "engine": "InnoDB", 
+ "actions": [],
+ "autoname": "EDU-SLA-.YYYY.-.#####",
+ "creation": "2016-11-28 15:38:54.793854",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "student",
+  "student_name",
+  "column_break_3",
+  "from_date",
+  "to_date",
+  "section_break_5",
+  "attendance_based_on",
+  "student_group",
+  "course_schedule",
+  "mark_as_present",
+  "column_break_11",
+  "reason",
+  "amended_from"
+ ],
  "fields": [
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "student", 
-   "fieldtype": "Link", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 1, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Student", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Student", 
-   "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": "student",
+   "fieldtype": "Link",
+   "in_global_search": 1,
+   "label": "Student",
+   "options": "Student",
+   "reqd": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fetch_from": "student.title", 
-   "fieldname": "student_name", 
-   "fieldtype": "Read Only", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 1, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Student Name", 
-   "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
-  }, 
+   "fetch_from": "student.title",
+   "fieldname": "student_name",
+   "fieldtype": "Read Only",
+   "in_global_search": 1,
+   "label": "Student Name",
+   "read_only": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "column_break_3", 
-   "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, 
-   "label": "", 
-   "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_3",
+   "fieldtype": "Column Break"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 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": 1, 
-   "label": "From 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": "from_date",
+   "fieldtype": "Date",
+   "in_list_view": 1,
+   "in_standard_filter": 1,
+   "label": "From Date",
+   "reqd": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 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, 
-   "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": "to_date",
+   "fieldtype": "Date",
+   "in_list_view": 1,
+   "label": "To Date",
+   "reqd": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "description": "Will show the student as Present in Student Monthly Attendance Report", 
-   "fieldname": "mark_as_present", 
-   "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": "Mark as Present", 
-   "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
-  }, 
+   "default": "0",
+   "description": "Check this to mark the student as present in case the student is not attending the institute to participate or represent the institute in any event.\n\n",
+   "fieldname": "mark_as_present",
+   "fieldtype": "Check",
+   "label": "Mark as Present"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "section_break_5", 
-   "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_5",
+   "fieldtype": "Section Break"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "reason", 
-   "fieldtype": "Text", 
-   "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": "Reason", 
-   "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": "reason",
+   "fieldtype": "Text",
+   "label": "Reason"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 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": "Student Leave Application", 
-   "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": "Student Leave Application",
+   "print_hide": 1,
+   "read_only": 1
+  },
+  {
+   "allow_in_quick_entry": 1,
+   "default": "Student Group",
+   "fieldname": "attendance_based_on",
+   "fieldtype": "Select",
+   "label": "Attendance Based On",
+   "options": "Student Group\nCourse Schedule"
+  },
+  {
+   "allow_in_quick_entry": 1,
+   "depends_on": "eval:doc.attendance_based_on === \"Student Group\";",
+   "fieldname": "student_group",
+   "fieldtype": "Link",
+   "label": "Student Group",
+   "mandatory_depends_on": "eval:doc.attendance_based_on === \"Student Group\";",
+   "options": "Student Group"
+  },
+  {
+   "allow_in_quick_entry": 1,
+   "depends_on": "eval:doc.attendance_based_on === \"Course Schedule\";",
+   "fieldname": "course_schedule",
+   "fieldtype": "Link",
+   "label": "Course Schedule",
+   "mandatory_depends_on": "eval:doc.attendance_based_on === \"Course Schedule\";",
+   "options": "Course Schedule"
+  },
+  {
+   "fieldname": "column_break_11",
+   "fieldtype": "Column Break"
   }
- ], 
- "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": "2018-08-21 16:15:50.807352", 
- "modified_by": "Administrator", 
- "module": "Education", 
- "name": "Student Leave Application", 
- "name_case": "", 
- "owner": "Administrator", 
+ ],
+ "is_submittable": 1,
+ "links": [],
+ "modified": "2020-07-08 13:22:38.329002",
+ "modified_by": "Administrator",
+ "module": "Education",
+ "name": "Student Leave Application",
+ "owner": "Administrator",
  "permissions": [
   {
-   "amend": 1, 
-   "cancel": 1, 
-   "create": 1, 
-   "delete": 1, 
-   "email": 1, 
-   "export": 0, 
-   "if_owner": 0, 
-   "import": 0, 
-   "permlevel": 0, 
-   "print": 1, 
-   "read": 1, 
-   "report": 1, 
-   "role": "Instructor", 
-   "set_user_permissions": 0, 
-   "share": 0, 
-   "submit": 1, 
+   "amend": 1,
+   "cancel": 1,
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "Instructor",
+   "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": "Academics 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": "Academics User",
+   "share": 1,
+   "submit": 1,
    "write": 1
   }
- ], 
- "quick_entry": 1, 
- "read_only": 0, 
- "read_only_onload": 0, 
- "restrict_to_domain": "Education", 
- "show_name_in_global_search": 1, 
- "sort_field": "modified", 
- "sort_order": "DESC", 
- "title_field": "student_name", 
- "track_changes": 0, 
- "track_seen": 0, 
- "track_views": 0
+ ],
+ "quick_entry": 1,
+ "restrict_to_domain": "Education",
+ "show_name_in_global_search": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "title_field": "student_name"
 }
\ No newline at end of file
diff --git a/erpnext/education/doctype/student_leave_application/student_leave_application.py b/erpnext/education/doctype/student_leave_application/student_leave_application.py
index 410f0cc..c8841c9 100644
--- a/erpnext/education/doctype/student_leave_application/student_leave_application.py
+++ b/erpnext/education/doctype/student_leave_application/student_leave_application.py
@@ -5,17 +5,23 @@
 from __future__ import unicode_literals
 import frappe
 from frappe import _
-from frappe.utils import get_link_to_form
+from datetime import timedelta
+from frappe.utils import get_link_to_form, getdate
 from frappe.model.document import Document
-from frappe import throw, _
 
 class StudentLeaveApplication(Document):
 	def validate(self):
-		self.validate_dates()
 		self.validate_duplicate()
+		self.validate_from_to_dates('from_date', 'to_date')
+
+	def on_submit(self):
+		self.update_attendance()
+
+	def on_cancel(self):
+		self.cancel_attendance()
 
 	def validate_duplicate(self):
-		data = frappe.db.sql(""" select name from `tabStudent Leave Application`
+		data = frappe.db.sql("""select name from `tabStudent Leave Application`
 			where
 				((%(from_date)s > from_date and %(from_date)s < to_date) or
 				(%(to_date)s > from_date and %(to_date)s < to_date) or
@@ -29,10 +35,57 @@
 		}, as_dict=1)
 
 		if data:
-			link = get_link_to_form("Student Leave Application", data[0].name)
-			frappe.throw(_("Leave application {0} already exists against the student {1}")
-				.format(link, self.student))
+			link = get_link_to_form('Student Leave Application', data[0].name)
+			frappe.throw(_('Leave application {0} already exists against the student {1}')
+				.format(link, frappe.bold(self.student)), title=_('Duplicate Entry'))
 
-	def validate_dates(self):
-		if self.to_date < self.from_date :
-			throw(_("To Date cannot be less than From Date"))
\ No newline at end of file
+	def update_attendance(self):
+		for dt in daterange(getdate(self.from_date), getdate(self.to_date)):
+			date = dt.strftime('%Y-%m-%d')
+
+			attendance = frappe.db.exists('Student Attendance', {
+				'student': self.student,
+				'date': date,
+				'docstatus': ('!=', 2)
+			})
+
+			status = 'Present' if self.mark_as_present else 'Absent'
+			if attendance:
+				# update existing attendance record
+				values = dict()
+				values['status'] = status
+				values['leave_application'] = self.name
+				frappe.db.set_value('Student Attendance', attendance, values)
+			else:
+				# make a new attendance record
+				doc = frappe.new_doc('Student Attendance')
+				doc.student = self.student
+				doc.student_name = self.student_name
+				doc.date = date
+				doc.leave_application = self.name
+				doc.status = status
+				if self.attendance_based_on == 'Student Group':
+					doc.student_group = self.student_group
+				else:
+					doc.course_schedule = self.course_schedule
+				doc.insert(ignore_permissions=True, ignore_mandatory=True)
+				doc.submit()
+
+	def cancel_attendance(self):
+		if self.docstatus == 2:
+			attendance = frappe.db.sql("""
+				SELECT name
+				FROM `tabStudent Attendance`
+				WHERE
+					student = %s and
+					(date between %s and %s) and
+					docstatus < 2
+			""", (self.student, self.from_date, self.to_date), as_dict=1)
+
+			for name in attendance:
+				frappe.db.set_value('Student Attendance', name, 'docstatus', 2)
+
+
+def daterange(start_date, end_date):
+	for n in range(int ((end_date - start_date).days)+1):
+		yield start_date + timedelta(n)
diff --git a/erpnext/education/doctype/student_leave_application/student_leave_application_dashboard.py b/erpnext/education/doctype/student_leave_application/student_leave_application_dashboard.py
new file mode 100644
index 0000000..fdcc147
--- /dev/null
+++ b/erpnext/education/doctype/student_leave_application/student_leave_application_dashboard.py
@@ -0,0 +1,11 @@
+from __future__ import unicode_literals
+
+def get_data():
+	return {
+		'fieldname': 'leave_application',
+		'transactions': [
+			{
+				'items': ['Student Attendance']
+			}
+		]
+	}
\ No newline at end of file
diff --git a/erpnext/education/doctype/student_leave_application/test_student_leave_application.py b/erpnext/education/doctype/student_leave_application/test_student_leave_application.py
index ddb30ac..e9b568a 100644
--- a/erpnext/education/doctype/student_leave_application/test_student_leave_application.py
+++ b/erpnext/education/doctype/student_leave_application/test_student_leave_application.py
@@ -5,8 +5,66 @@
 
 import frappe
 import unittest
-
-# test_records = frappe.get_test_records('Student Leave Application')
+from frappe.utils import getdate, add_days
+from erpnext.education.doctype.student_group.test_student_group import get_random_group
+from erpnext.education.doctype.student.test_student import create_student
 
 class TestStudentLeaveApplication(unittest.TestCase):
-	pass
+	def setUp(self):
+		frappe.db.sql("""delete from `tabStudent Leave Application`""")
+
+	def test_attendance_record_creation(self):
+		leave_application = create_leave_application()
+		attendance_record = frappe.db.exists('Student Attendance', {'leave_application': leave_application.name, 'status': 'Absent'})
+		self.assertTrue(attendance_record)
+
+		# mark as present
+		date = add_days(getdate(), -1)
+		leave_application = create_leave_application(date, date, 1)
+		attendance_record = frappe.db.exists('Student Attendance', {'leave_application': leave_application.name, 'status': 'Present'})
+		self.assertTrue(attendance_record)
+
+	def test_attendance_record_updated(self):
+		attendance = create_student_attendance()
+		create_leave_application()
+		self.assertEqual(frappe.db.get_value('Student Attendance', attendance.name, 'status'), 'Absent')
+
+	def test_attendance_record_cancellation(self):
+		leave_application = create_leave_application()
+		leave_application.cancel()
+		attendance_status = frappe.db.get_value('Student Attendance', {'leave_application': leave_application.name}, 'docstatus')
+		self.assertTrue(attendance_status, 2)
+
+
+def create_leave_application(from_date=None, to_date=None, mark_as_present=0):
+	student = get_student()
+
+	leave_application = frappe.get_doc({
+		'doctype': 'Student Leave Application',
+		'student': student.name,
+		'attendance_based_on': 'Student Group',
+		'student_group': get_random_group().name,
+		'from_date': from_date if from_date else getdate(),
+		'to_date': from_date if from_date else getdate(),
+		'mark_as_present': mark_as_present
+	}).insert()
+	leave_application.submit()
+	return leave_application
+
+def create_student_attendance(date=None, status=None):
+	student = get_student()
+	attendance = frappe.get_doc({
+		'doctype': 'Student Attendance',
+		'student': student.name,
+		'status': status if status else 'Present',
+		'date': date if date else getdate(),
+		'student_group': get_random_group().name
+	}).insert()
+	return attendance
+
+def get_student():
+	return create_student(dict(
+		email='test_student@gmail.com',
+		first_name='Test',
+		last_name='Student'
+	))
\ No newline at end of file
diff --git a/erpnext/education/doctype/student_report_generation_tool/student_report_generation_tool.py b/erpnext/education/doctype/student_report_generation_tool/student_report_generation_tool.py
index c0a7359..17bc367 100644
--- a/erpnext/education/doctype/student_report_generation_tool/student_report_generation_tool.py
+++ b/erpnext/education/doctype/student_report_generation_tool/student_report_generation_tool.py
@@ -80,7 +80,7 @@
 		from_date, to_date = frappe.db.get_value("Academic Term", academic_term, ["term_start_date", "term_end_date"])
 	if from_date and to_date:
 		attendance = dict(frappe.db.sql('''select status, count(student) as no_of_days
-			from `tabStudent Attendance` where student = %s
+			from `tabStudent Attendance` where student = %s and docstatus = 1
 			and date between %s and %s group by status''',
 			(student, from_date, to_date)))
 		if "Absent" not in attendance.keys():
diff --git a/erpnext/education/doctype/topic/topic.js b/erpnext/education/doctype/topic/topic.js
index 695c174..2002b0c 100644
--- a/erpnext/education/doctype/topic/topic.js
+++ b/erpnext/education/doctype/topic/topic.js
@@ -3,6 +3,53 @@
 
 frappe.ui.form.on('Topic', {
 	refresh: function(frm) {
+		if (!cur_frm.doc.__islocal) {
+			frm.add_custom_button(__('Add to Courses'), function() {
+				frm.trigger('add_topic_to_courses');
+			}, __('Action'));
+		}
+	},
 
+	add_topic_to_courses: function(frm) {
+		get_courses_without_topic(frm.doc.name).then(r => {
+			if (r.message.length) {
+				frappe.prompt([
+					{
+						fieldname: 'courses',
+						label: __('Courses'),
+						fieldtype: 'MultiSelectPills',
+						get_data: function() {
+							return r.message;
+						}
+					}
+				],
+				function(data) {
+					frappe.call({
+						method: 'erpnext.education.doctype.topic.topic.add_topic_to_courses',
+						args: {
+							'topic': frm.doc.name,
+							'courses': data.courses
+						},
+						callback: function(r) {
+							if (!r.exc) {
+								frm.reload_doc();
+							}
+						},
+						freeze: true,
+						freeze_message: __('...Adding Topic to Courses')
+					});
+				}, __('Add Topic to Courses'), __('Add'));
+			} else {
+				frappe.msgprint(__('This topic is already added to the existing courses'));
+			}
+		});
 	}
 });
+
+let get_courses_without_topic = function(topic) {
+	return frappe.call({
+		type: 'GET',
+		method: 'erpnext.education.doctype.topic.topic.get_courses_without_topic',
+		args: {'topic': topic}
+	});
+};
\ No newline at end of file
diff --git a/erpnext/education/doctype/topic/topic.py b/erpnext/education/doctype/topic/topic.py
index 7e5da32..a5253e9 100644
--- a/erpnext/education/doctype/topic/topic.py
+++ b/erpnext/education/doctype/topic/topic.py
@@ -4,6 +4,8 @@
 
 from __future__ import unicode_literals
 import frappe
+import json
+from frappe import _
 from frappe.model.document import Document
 
 class Topic(Document):
@@ -14,4 +16,44 @@
 		except Exception as e:
 			frappe.log_error(frappe.get_traceback())
 			return None
-		return content_data
\ No newline at end of file
+		return content_data
+
+@frappe.whitelist()
+def get_courses_without_topic(topic):
+	data = []
+	for entry in frappe.db.get_all('Course'):
+		course = frappe.get_doc('Course', entry.name)
+		topics = [t.topic for t in course.topics]
+		if not topics or topic not in topics:
+			data.append(course.name)
+	return data
+
+@frappe.whitelist()
+def add_topic_to_courses(topic, courses, mandatory=False):
+	courses = json.loads(courses)
+	for entry in courses:
+		course = frappe.get_doc('Course', entry)
+		course.append('topics', {
+			'topic': topic,
+			'topic_name': topic
+		})
+		course.flags.ignore_mandatory = True
+		course.save()
+	frappe.db.commit()
+	frappe.msgprint(_('Topic {0} has been added to all the selected courses successfully.').format(frappe.bold(topic)),
+		title=_('Courses updated'), indicator='green')
+
+@frappe.whitelist()
+def add_content_to_topics(content_type, content, topics):
+	topics = json.loads(topics)
+	for entry in topics:
+		topic = frappe.get_doc('Topic', entry)
+		topic.append('topic_content', {
+			'content_type': content_type,
+			'content': content,
+		})
+		topic.flags.ignore_mandatory = True
+		topic.save()
+	frappe.db.commit()
+	frappe.msgprint(_('{0} {1} has been added to all the selected topics successfully.').format(content_type, frappe.bold(content)),
+		title=_('Topics updated'), indicator='green')
\ No newline at end of file
diff --git a/erpnext/education/report/absent_student_report/absent_student_report.json b/erpnext/education/report/absent_student_report/absent_student_report.json
index 0d5eeba..92ad860 100644
--- a/erpnext/education/report/absent_student_report/absent_student_report.json
+++ b/erpnext/education/report/absent_student_report/absent_student_report.json
@@ -1,20 +1,21 @@
 {
- "add_total_row": 0, 
- "apply_user_permissions": 1, 
- "creation": "2013-05-13 14:04:03", 
- "disabled": 0, 
- "docstatus": 0, 
- "doctype": "Report", 
- "idx": 3, 
- "is_standard": "Yes", 
- "modified": "2017-11-10 19:42:36.457449", 
- "modified_by": "Administrator", 
- "module": "Education", 
- "name": "Absent Student Report", 
- "owner": "Administrator", 
- "ref_doctype": "Student Attendance", 
- "report_name": "Absent Student Report", 
- "report_type": "Script Report", 
+ "add_total_row": 0,
+ "creation": "2013-05-13 14:04:03",
+ "disable_prepared_report": 0,
+ "disabled": 0,
+ "docstatus": 0,
+ "doctype": "Report",
+ "idx": 3,
+ "is_standard": "Yes",
+ "modified": "2020-06-24 17:16:40.251116",
+ "modified_by": "Administrator",
+ "module": "Education",
+ "name": "Absent Student Report",
+ "owner": "Administrator",
+ "prepared_report": 0,
+ "ref_doctype": "Student Attendance",
+ "report_name": "Absent Student Report",
+ "report_type": "Script Report",
  "roles": [
   {
    "role": "Academics User"
diff --git a/erpnext/education/report/absent_student_report/absent_student_report.py b/erpnext/education/report/absent_student_report/absent_student_report.py
index 8e6ce51..4e57cc6 100644
--- a/erpnext/education/report/absent_student_report/absent_student_report.py
+++ b/erpnext/education/report/absent_student_report/absent_student_report.py
@@ -11,7 +11,7 @@
 
 	if not filters.get("date"):
 		msgprint(_("Please select date"), raise_exception=1)
-	
+
 	columns = get_columns(filters)
 	date = filters.get("date")
 
@@ -26,27 +26,27 @@
 		if not student.student in leave_applicants:
 			row = [student.student, student.student_name, student.student_group]
 			stud_details = frappe.db.get_value("Student", student.student, ['student_email_id', 'student_mobile_number'], as_dict=True)
-			
+
 			if stud_details.student_email_id:
 				row+=[stud_details.student_email_id]
 			else:
 				row+= [""]
-			
+
 			if stud_details.student_mobile_number:
 				row+=[stud_details.student_mobile_number]
 			else:
 				row+= [""]
 			if transportation_details.get(student.student):
 				row += transportation_details.get(student.student)
-				
+
 			data.append(row)
-	
+
 	return columns, data
 
 def get_columns(filters):
-	columns = [ 
-		_("Student") + ":Link/Student:90", 
-		_("Student Name") + "::150", 
+	columns = [
+		_("Student") + ":Link/Student:90",
+		_("Student Name") + "::150",
 		_("Student Group") + "::180",
 		_("Student Email Address") + "::180",
 		_("Student Mobile No.") + "::150",
@@ -56,15 +56,29 @@
 	return columns
 
 def get_absent_students(date):
-	absent_students = frappe.db.sql("""select student, student_name, student_group from `tabStudent Attendance` 
-		where status="Absent" and date = %s order by student_group, student_name""", date, as_dict=1)
+	absent_students = frappe.db.sql("""
+		SELECT student, student_name, student_group
+		FROM `tabStudent Attendance`
+		WHERE
+			status='Absent' and docstatus=1 and date = %s
+		ORDER BY
+			student_group, student_name""",
+	date, as_dict=1)
 	return absent_students
 
 def get_leave_applications(date):
 	leave_applicants = []
-	for student in frappe.db.sql("""select student from `tabStudent Leave Application` 
-	where docstatus = 1 and from_date <= %s and to_date >= %s""", (date, date)):
+	leave_applications = frappe.db.sql("""
+		SELECT student
+		FROM
+			`tabStudent Leave Application`
+		WHERE
+			docstatus = 1 and mark_as_present = 1 and
+			from_date <= %s and to_date >= %s
+	""", (date, date))
+	for student in leave_applications:
 		leave_applicants.append(student[0])
+
 	return leave_applicants
 
 def get_transportation_details(date, student_list):
diff --git a/erpnext/education/report/assessment_plan_status/assessment_plan_status.json b/erpnext/education/report/assessment_plan_status/assessment_plan_status.json
index 3000bec..cbca648 100644
--- a/erpnext/education/report/assessment_plan_status/assessment_plan_status.json
+++ b/erpnext/education/report/assessment_plan_status/assessment_plan_status.json
@@ -1,20 +1,21 @@
 {
- "add_total_row": 0, 
- "apply_user_permissions": 1, 
- "creation": "2017-11-09 15:07:30.404428", 
- "disabled": 0, 
- "docstatus": 0, 
- "doctype": "Report", 
- "idx": 0, 
- "is_standard": "Yes", 
- "modified": "2017-11-28 18:35:44.903665", 
- "modified_by": "Administrator", 
- "module": "Education", 
- "name": "Assessment Plan Status", 
- "owner": "Administrator", 
- "ref_doctype": "Assessment Plan", 
- "report_name": "Assessment Plan Status", 
- "report_type": "Script Report", 
+ "add_total_row": 0,
+ "creation": "2017-11-09 15:07:30.404428",
+ "disable_prepared_report": 0,
+ "disabled": 0,
+ "docstatus": 0,
+ "doctype": "Report",
+ "idx": 0,
+ "is_standard": "Yes",
+ "modified": "2020-06-24 17:16:02.027410",
+ "modified_by": "Administrator",
+ "module": "Education",
+ "name": "Assessment Plan Status",
+ "owner": "Administrator",
+ "prepared_report": 0,
+ "ref_doctype": "Assessment Plan",
+ "report_name": "Assessment Plan Status",
+ "report_type": "Script Report",
  "roles": [
   {
    "role": "Academics User"
diff --git a/erpnext/education/report/course_wise_assessment_report/course_wise_assessment_report.json b/erpnext/education/report/course_wise_assessment_report/course_wise_assessment_report.json
index 61976b4..416db9d 100644
--- a/erpnext/education/report/course_wise_assessment_report/course_wise_assessment_report.json
+++ b/erpnext/education/report/course_wise_assessment_report/course_wise_assessment_report.json
@@ -1,24 +1,26 @@
 {
- "add_total_row": 0, 
- "apply_user_permissions": 1, 
- "creation": "2017-05-05 14:46:13.776133", 
- "disabled": 0, 
- "docstatus": 0, 
- "doctype": "Report", 
- "idx": 0, 
- "is_standard": "Yes", 
- "modified": "2018-02-08 15:11:24.904628", 
- "modified_by": "Administrator", 
- "module": "Education", 
- "name": "Course wise Assessment Report", 
- "owner": "Administrator", 
- "ref_doctype": "Assessment Result", 
- "report_name": "Course wise Assessment Report", 
- "report_type": "Script Report", 
+ "add_total_row": 0,
+ "creation": "2017-05-05 14:46:13.776133",
+ "disable_prepared_report": 0,
+ "disabled": 0,
+ "docstatus": 0,
+ "doctype": "Report",
+ "idx": 0,
+ "is_standard": "Yes",
+ "modified": "2020-06-24 17:15:15.477530",
+ "modified_by": "Administrator",
+ "module": "Education",
+ "name": "Course wise Assessment Report",
+ "owner": "Administrator",
+ "prepared_report": 0,
+ "query": "",
+ "ref_doctype": "Assessment Result",
+ "report_name": "Course wise Assessment Report",
+ "report_type": "Script Report",
  "roles": [
   {
    "role": "Instructor"
-  }, 
+  },
   {
    "role": "Education Manager"
   }
diff --git a/erpnext/education/report/final_assessment_grades/final_assessment_grades.json b/erpnext/education/report/final_assessment_grades/final_assessment_grades.json
index 4d444b4..6a23494 100644
--- a/erpnext/education/report/final_assessment_grades/final_assessment_grades.json
+++ b/erpnext/education/report/final_assessment_grades/final_assessment_grades.json
@@ -1,24 +1,25 @@
 {
- "add_total_row": 0, 
- "apply_user_permissions": 1, 
- "creation": "2018-01-22 17:04:43.412054", 
- "disabled": 0, 
- "docstatus": 0, 
- "doctype": "Report", 
- "idx": 0, 
- "is_standard": "Yes", 
- "modified": "2019-02-08 15:11:35.339434", 
- "modified_by": "Administrator", 
- "module": "Education", 
- "name": "Final Assessment Grades", 
- "owner": "Administrator", 
- "ref_doctype": "Assessment Result", 
- "report_name": "Final Assessment Grades", 
- "report_type": "Script Report", 
+ "add_total_row": 0,
+ "creation": "2018-01-22 17:04:43.412054",
+ "disable_prepared_report": 0,
+ "disabled": 0,
+ "docstatus": 0,
+ "doctype": "Report",
+ "idx": 0,
+ "is_standard": "Yes",
+ "modified": "2020-06-24 17:13:35.373756",
+ "modified_by": "Administrator",
+ "module": "Education",
+ "name": "Final Assessment Grades",
+ "owner": "Administrator",
+ "prepared_report": 0,
+ "ref_doctype": "Assessment Result",
+ "report_name": "Final Assessment Grades",
+ "report_type": "Script Report",
  "roles": [
   {
    "role": "Instructor"
-  }, 
+  },
   {
    "role": "Education Manager"
   }
diff --git a/erpnext/education/report/student_and_guardian_contact_details/student_and_guardian_contact_details.json b/erpnext/education/report/student_and_guardian_contact_details/student_and_guardian_contact_details.json
index fe7d158..fa9be65 100644
--- a/erpnext/education/report/student_and_guardian_contact_details/student_and_guardian_contact_details.json
+++ b/erpnext/education/report/student_and_guardian_contact_details/student_and_guardian_contact_details.json
@@ -1,24 +1,25 @@
 {
- "add_total_row": 0, 
- "apply_user_permissions": 1, 
- "creation": "2017-03-27 17:47:16.831433", 
- "disabled": 0, 
- "docstatus": 0, 
- "doctype": "Report", 
- "idx": 0, 
- "is_standard": "Yes", 
- "modified": "2017-11-10 19:42:30.300729", 
- "modified_by": "Administrator", 
- "module": "Education", 
- "name": "Student and Guardian Contact Details", 
- "owner": "Administrator", 
- "ref_doctype": "Program Enrollment", 
- "report_name": "Student and Guardian Contact Details", 
- "report_type": "Script Report", 
+ "add_total_row": 0,
+ "creation": "2017-03-27 17:47:16.831433",
+ "disable_prepared_report": 0,
+ "disabled": 0,
+ "docstatus": 0,
+ "doctype": "Report",
+ "idx": 0,
+ "is_standard": "Yes",
+ "modified": "2020-06-24 17:16:50.639488",
+ "modified_by": "Administrator",
+ "module": "Education",
+ "name": "Student and Guardian Contact Details",
+ "owner": "Administrator",
+ "prepared_report": 0,
+ "ref_doctype": "Program Enrollment",
+ "report_name": "Student and Guardian Contact Details",
+ "report_type": "Script Report",
  "roles": [
   {
    "role": "Instructor"
-  }, 
+  },
   {
    "role": "Academics User"
   }
diff --git a/erpnext/education/report/student_batch_wise_attendance/student_batch_wise_attendance.json b/erpnext/education/report/student_batch_wise_attendance/student_batch_wise_attendance.json
index eb547b7..8baf8f9 100644
--- a/erpnext/education/report/student_batch_wise_attendance/student_batch_wise_attendance.json
+++ b/erpnext/education/report/student_batch_wise_attendance/student_batch_wise_attendance.json
@@ -1,20 +1,21 @@
 {
- "add_total_row": 0, 
- "apply_user_permissions": 1, 
- "creation": "2016-11-28 22:07:03.859124", 
- "disabled": 0, 
- "docstatus": 0, 
- "doctype": "Report", 
- "idx": 2, 
- "is_standard": "Yes", 
- "modified": "2017-11-10 19:41:12.328346", 
- "modified_by": "Administrator", 
- "module": "Education", 
- "name": "Student Batch-Wise Attendance", 
- "owner": "Administrator", 
- "ref_doctype": "Student Attendance", 
- "report_name": "Student Batch-Wise Attendance", 
- "report_type": "Script Report", 
+ "add_total_row": 0,
+ "creation": "2016-11-28 22:07:03.859124",
+ "disable_prepared_report": 0,
+ "disabled": 0,
+ "docstatus": 0,
+ "doctype": "Report",
+ "idx": 2,
+ "is_standard": "Yes",
+ "modified": "2020-06-24 17:16:59.823709",
+ "modified_by": "Administrator",
+ "module": "Education",
+ "name": "Student Batch-Wise Attendance",
+ "owner": "Administrator",
+ "prepared_report": 0,
+ "ref_doctype": "Student Attendance",
+ "report_name": "Student Batch-Wise Attendance",
+ "report_type": "Script Report",
  "roles": [
   {
    "role": "Academics User"
diff --git a/erpnext/education/report/student_batch_wise_attendance/student_batch_wise_attendance.py b/erpnext/education/report/student_batch_wise_attendance/student_batch_wise_attendance.py
index 646e3f7..c65d233 100644
--- a/erpnext/education/report/student_batch_wise_attendance/student_batch_wise_attendance.py
+++ b/erpnext/education/report/student_batch_wise_attendance/student_batch_wise_attendance.py
@@ -11,7 +11,7 @@
 
 	if not filters.get("date"):
 		msgprint(_("Please select date"), raise_exception=1)
-	
+
 	columns = get_columns(filters)
 
 	active_student_group = get_active_student_group()
@@ -37,28 +37,28 @@
 	return columns, data
 
 def get_columns(filters):
-	columns = [ 
-		_("Student Group") + ":Link/Student Group:250", 
-		_("Student Group Strength") + "::170", 
-		_("Present") + "::90", 
+	columns = [
+		_("Student Group") + ":Link/Student Group:250",
+		_("Student Group Strength") + "::170",
+		_("Present") + "::90",
 		_("Absent") + "::90",
 		_("Not Marked") + "::90"
 	]
 	return columns
 
 def get_active_student_group():
-	active_student_groups = frappe.db.sql("""select name from `tabStudent Group` where group_based_on = "Batch" 
+	active_student_groups = frappe.db.sql("""select name from `tabStudent Group` where group_based_on = "Batch"
 		and academic_year=%s order by name""", (frappe.defaults.get_defaults().academic_year), as_dict=1)
 	return active_student_groups
 
 def get_student_group_strength(student_group):
-	student_group_strength = frappe.db.sql("""select count(*) from `tabStudent Group Student` 
+	student_group_strength = frappe.db.sql("""select count(*) from `tabStudent Group Student`
 		where parent = %s and active=1""", student_group)[0][0]
 	return student_group_strength
 
 def get_student_attendance(student_group, date):
-	student_attendance = frappe.db.sql("""select count(*) as count, status from `tabStudent Attendance` where \
-				student_group= %s and date= %s and\
+	student_attendance = frappe.db.sql("""select count(*) as count, status from `tabStudent Attendance` where
+				student_group= %s and date= %s and docstatus = 1 and
 				(course_schedule is Null or course_schedule='') group by status""",
 				(student_group, date), as_dict=1)
 	return student_attendance
\ No newline at end of file
diff --git a/erpnext/education/report/student_fee_collection/student_fee_collection.json b/erpnext/education/report/student_fee_collection/student_fee_collection.json
index eb945cf..8deb865 100644
--- a/erpnext/education/report/student_fee_collection/student_fee_collection.json
+++ b/erpnext/education/report/student_fee_collection/student_fee_collection.json
@@ -1,21 +1,22 @@
 {
- "add_total_row": 0, 
- "creation": "2016-06-22 02:58:41.024538", 
- "disabled": 0, 
- "docstatus": 0, 
- "doctype": "Report", 
- "idx": 3, 
- "is_standard": "Yes", 
- "modified": "2018-12-17 16:46:46.176620", 
- "modified_by": "Administrator", 
- "module": "Education", 
- "name": "Student Fee Collection", 
- "owner": "Administrator", 
- "prepared_report": 0, 
- "query": "SELECT\n student as \"Student:Link/Student:200\",\n student_name as \"Student Name::200\",\n sum(grand_total) - sum(outstanding_amount) as \"Paid Amount:Currency:150\",\n sum(outstanding_amount) as \"Outstanding Amount:Currency:150\",\n sum(grand_total) as \"Grand Total:Currency:150\"\nFROM\n `tabFees` \nGROUP BY\n student", 
- "ref_doctype": "Fees", 
- "report_name": "Student Fee Collection", 
- "report_type": "Query Report", 
+ "add_total_row": 0,
+ "creation": "2016-06-22 02:58:41.024538",
+ "disable_prepared_report": 0,
+ "disabled": 0,
+ "docstatus": 0,
+ "doctype": "Report",
+ "idx": 3,
+ "is_standard": "Yes",
+ "modified": "2020-06-24 17:14:39.452551",
+ "modified_by": "Administrator",
+ "module": "Education",
+ "name": "Student Fee Collection",
+ "owner": "Administrator",
+ "prepared_report": 0,
+ "query": "SELECT\n student as \"Student:Link/Student:200\",\n student_name as \"Student Name::200\",\n sum(grand_total) - sum(outstanding_amount) as \"Paid Amount:Currency:150\",\n sum(outstanding_amount) as \"Outstanding Amount:Currency:150\",\n sum(grand_total) as \"Grand Total:Currency:150\"\nFROM\n `tabFees` \nGROUP BY\n student",
+ "ref_doctype": "Fees",
+ "report_name": "Student Fee Collection",
+ "report_type": "Query Report",
  "roles": [
   {
    "role": "Academics User"
diff --git a/erpnext/education/report/student_monthly_attendance_sheet/student_monthly_attendance_sheet.json b/erpnext/education/report/student_monthly_attendance_sheet/student_monthly_attendance_sheet.json
index e10f190..1423d4f 100644
--- a/erpnext/education/report/student_monthly_attendance_sheet/student_monthly_attendance_sheet.json
+++ b/erpnext/education/report/student_monthly_attendance_sheet/student_monthly_attendance_sheet.json
@@ -1,20 +1,21 @@
 {
- "add_total_row": 0, 
- "apply_user_permissions": 1, 
- "creation": "2013-05-13 14:04:03", 
- "disabled": 0, 
- "docstatus": 0, 
- "doctype": "Report", 
- "idx": 3, 
- "is_standard": "Yes", 
- "modified": "2017-11-10 19:42:43.376658", 
- "modified_by": "Administrator", 
- "module": "Education", 
- "name": "Student Monthly Attendance Sheet", 
- "owner": "Administrator", 
- "ref_doctype": "Student Attendance", 
- "report_name": "Student Monthly Attendance Sheet", 
- "report_type": "Script Report", 
+ "add_total_row": 0,
+ "creation": "2013-05-13 14:04:03",
+ "disable_prepared_report": 0,
+ "disabled": 0,
+ "docstatus": 0,
+ "doctype": "Report",
+ "idx": 3,
+ "is_standard": "Yes",
+ "modified": "2020-06-24 17:16:13.307053",
+ "modified_by": "Administrator",
+ "module": "Education",
+ "name": "Student Monthly Attendance Sheet",
+ "owner": "Administrator",
+ "prepared_report": 0,
+ "ref_doctype": "Student Attendance",
+ "report_name": "Student Monthly Attendance Sheet",
+ "report_type": "Script Report",
  "roles": [
   {
    "role": "Academics User"
diff --git a/erpnext/education/report/student_monthly_attendance_sheet/student_monthly_attendance_sheet.py b/erpnext/education/report/student_monthly_attendance_sheet/student_monthly_attendance_sheet.py
index 3f1d5b3..d820bfb 100644
--- a/erpnext/education/report/student_monthly_attendance_sheet/student_monthly_attendance_sheet.py
+++ b/erpnext/education/report/student_monthly_attendance_sheet/student_monthly_attendance_sheet.py
@@ -57,8 +57,9 @@
 	return student_list
 
 def get_attendance_list(from_date, to_date, student_group, students_list):
-	attendance_list = frappe.db.sql('''select student, date, status 
-		from `tabStudent Attendance` where student_group = %s 
+	attendance_list = frappe.db.sql('''select student, date, status
+		from `tabStudent Attendance` where student_group = %s
+		and docstatus = 1
 		and date between %s and %s
 		order by student, date''',
 		(student_group, from_date, to_date), as_dict=1)
@@ -75,10 +76,10 @@
 def get_students_with_leave_application(from_date, to_date, students_list):
 	if not students_list: return
 	leave_applications = frappe.db.sql("""
-		select student, from_date, to_date 
-		from `tabStudent Leave Application` 
-		where 
-			mark_as_present and docstatus = 1
+		select student, from_date, to_date
+		from `tabStudent Leave Application`
+		where
+			mark_as_present = 1 and docstatus = 1
 			and student in %(students)s
 			and (
 				from_date between %(from_date)s and %(to_date)s
diff --git a/erpnext/accounts/page/pos/__init__.py b/erpnext/erpnext_integrations/doctype/taxjar_settings/__init__.py
similarity index 100%
copy from erpnext/accounts/page/pos/__init__.py
copy to erpnext/erpnext_integrations/doctype/taxjar_settings/__init__.py
diff --git a/erpnext/erpnext_integrations/doctype/taxjar_settings/taxjar_settings.js b/erpnext/erpnext_integrations/doctype/taxjar_settings/taxjar_settings.js
new file mode 100644
index 0000000..62d5709
--- /dev/null
+++ b/erpnext/erpnext_integrations/doctype/taxjar_settings/taxjar_settings.js
@@ -0,0 +1,9 @@
+// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+frappe.ui.form.on('TaxJar Settings', {
+	is_sandbox: (frm) => {
+		frm.toggle_reqd("api_key", !frm.doc.is_sandbox);
+		frm.toggle_reqd("sandbox_api_key", frm.doc.is_sandbox);
+	}
+});
diff --git a/erpnext/erpnext_integrations/doctype/taxjar_settings/taxjar_settings.json b/erpnext/erpnext_integrations/doctype/taxjar_settings/taxjar_settings.json
new file mode 100644
index 0000000..c0d60f7
--- /dev/null
+++ b/erpnext/erpnext_integrations/doctype/taxjar_settings/taxjar_settings.json
@@ -0,0 +1,110 @@
+{
+ "actions": [],
+ "creation": "2017-06-15 08:21:24.624315",
+ "doctype": "DocType",
+ "document_type": "Setup",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "is_sandbox",
+  "taxjar_calculate_tax",
+  "taxjar_create_transactions",
+  "credentials",
+  "api_key",
+  "cb_keys",
+  "sandbox_api_key",
+  "configuration",
+  "tax_account_head",
+  "configuration_cb",
+  "shipping_account_head"
+ ],
+ "fields": [
+  {
+   "fieldname": "credentials",
+   "fieldtype": "Section Break",
+   "label": "Credentials"
+  },
+  {
+   "fieldname": "api_key",
+   "fieldtype": "Password",
+   "in_list_view": 1,
+   "label": "Live API Key",
+   "reqd": 1
+  },
+  {
+   "fieldname": "configuration",
+   "fieldtype": "Section Break",
+   "label": "Configuration"
+  },
+  {
+   "fieldname": "tax_account_head",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "label": "Tax Account Head",
+   "options": "Account",
+   "reqd": 1
+  },
+  {
+   "fieldname": "shipping_account_head",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "label": "Shipping Account Head",
+   "options": "Account",
+   "reqd": 1
+  },
+  {
+   "default": "0",
+   "fieldname": "is_sandbox",
+   "fieldtype": "Check",
+   "label": "Sandbox Mode"
+  },
+  {
+   "fieldname": "sandbox_api_key",
+   "fieldtype": "Password",
+   "label": "Sandbox API Key"
+  },
+  {
+   "fieldname": "configuration_cb",
+   "fieldtype": "Column Break"
+  },
+  {
+   "default": "0",
+   "fieldname": "taxjar_create_transactions",
+   "fieldtype": "Check",
+   "label": "Create TaxJar Transaction"
+  },
+  {
+   "default": "0",
+   "fieldname": "taxjar_calculate_tax",
+   "fieldtype": "Check",
+   "label": "Enable Tax Calculation"
+  },
+  {
+   "fieldname": "cb_keys",
+   "fieldtype": "Column Break"
+  }
+ ],
+ "issingle": 1,
+ "links": [],
+ "modified": "2020-04-30 04:38:03.311089",
+ "modified_by": "Administrator",
+ "module": "ERPNext Integrations",
+ "name": "TaxJar 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/erpnext_integrations/doctype/taxjar_settings/taxjar_settings.py b/erpnext/erpnext_integrations/doctype/taxjar_settings/taxjar_settings.py
new file mode 100644
index 0000000..7f5f0f0
--- /dev/null
+++ b/erpnext/erpnext_integrations/doctype/taxjar_settings/taxjar_settings.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 TaxJarSettings(Document):
+	pass
diff --git a/erpnext/erpnext_integrations/doctype/taxjar_settings/test_taxjar_settings.py b/erpnext/erpnext_integrations/doctype/taxjar_settings/test_taxjar_settings.py
new file mode 100644
index 0000000..7cdfd00
--- /dev/null
+++ b/erpnext/erpnext_integrations/doctype/taxjar_settings/test_taxjar_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 TestTaxJarSettings(unittest.TestCase):
+	pass
diff --git a/erpnext/erpnext_integrations/taxjar_integration.py b/erpnext/erpnext_integrations/taxjar_integration.py
new file mode 100644
index 0000000..633692d
--- /dev/null
+++ b/erpnext/erpnext_integrations/taxjar_integration.py
@@ -0,0 +1,251 @@
+import traceback
+
+import pycountry
+import taxjar
+
+import frappe
+from erpnext import get_default_company
+from frappe import _
+from frappe.contacts.doctype.address.address import get_company_address
+
+TAX_ACCOUNT_HEAD = frappe.db.get_single_value("TaxJar Settings", "tax_account_head")
+SHIP_ACCOUNT_HEAD = frappe.db.get_single_value("TaxJar Settings", "shipping_account_head")
+TAXJAR_CREATE_TRANSACTIONS = frappe.db.get_single_value("TaxJar Settings", "taxjar_create_transactions")
+TAXJAR_CALCULATE_TAX = frappe.db.get_single_value("TaxJar Settings", "taxjar_calculate_tax")
+SUPPORTED_COUNTRY_CODES = ["AT", "AU", "BE", "BG", "CA", "CY", "CZ", "DE", "DK", "EE", "ES", "FI",
+	"FR", "GB", "GR", "HR", "HU", "IE", "IT", "LT", "LU", "LV", "MT", "NL", "PL", "PT", "RO",
+	"SE", "SI", "SK", "US"]
+
+
+def get_client():
+	taxjar_settings = frappe.get_single("TaxJar Settings")
+
+	if not taxjar_settings.is_sandbox:
+		api_key = taxjar_settings.api_key and taxjar_settings.get_password("api_key")
+		api_url = taxjar.DEFAULT_API_URL
+	else:
+		api_key = taxjar_settings.sandbox_api_key and taxjar_settings.get_password("sandbox_api_key")
+		api_url = taxjar.SANDBOX_API_URL
+
+	if api_key and api_url:
+		return taxjar.Client(api_key=api_key, api_url=api_url)
+
+
+def create_transaction(doc, method):
+	"""Create an order transaction in TaxJar"""
+
+	if not TAXJAR_CREATE_TRANSACTIONS:
+		return
+
+	client = get_client()
+
+	if not client:
+		return
+
+	sales_tax = sum([tax.tax_amount for tax in doc.taxes if tax.account_head == TAX_ACCOUNT_HEAD])
+
+	if not sales_tax:
+		return
+
+	tax_dict = get_tax_data(doc)
+
+	if not tax_dict:
+		return
+
+	tax_dict['transaction_id'] = doc.name
+	tax_dict['transaction_date'] = frappe.utils.today()
+	tax_dict['sales_tax'] = sales_tax
+	tax_dict['amount'] = doc.total + tax_dict['shipping']
+
+	try:
+		client.create_order(tax_dict)
+	except taxjar.exceptions.TaxJarResponseError as err:
+		frappe.throw(_(sanitize_error_response(err)))
+	except Exception as ex:
+		print(traceback.format_exc(ex))
+
+
+def delete_transaction(doc, method):
+	"""Delete an existing TaxJar order transaction"""
+
+	if not TAXJAR_CREATE_TRANSACTIONS:
+		return
+
+	client = get_client()
+
+	if not client:
+		return
+
+	client.delete_order(doc.name)
+
+
+def get_tax_data(doc):
+	from_address = get_company_address_details(doc)
+	from_shipping_state = from_address.get("state")
+	from_country_code = frappe.db.get_value("Country", from_address.country, "code")
+	from_country_code = from_country_code.upper()
+
+	to_address = get_shipping_address_details(doc)
+	to_shipping_state = to_address.get("state")
+	to_country_code = frappe.db.get_value("Country", to_address.country, "code")
+	to_country_code = to_country_code.upper()
+
+	if to_country_code not in SUPPORTED_COUNTRY_CODES:
+		return
+
+	shipping = sum([tax.tax_amount for tax in doc.taxes if tax.account_head == SHIP_ACCOUNT_HEAD])
+
+	if to_shipping_state is not None:
+		to_shipping_state = get_iso_3166_2_state_code(to_address)
+
+	tax_dict = {
+		'from_country': from_country_code,
+		'from_zip': from_address.pincode,
+		'from_state': from_shipping_state,
+		'from_city': from_address.city,
+		'from_street': from_address.address_line1,
+		'to_country': to_country_code,
+		'to_zip': to_address.pincode,
+		'to_city': to_address.city,
+		'to_street': to_address.address_line1,
+		'to_state': to_shipping_state,
+		'shipping': shipping,
+		'amount': doc.net_total
+	}
+
+	return tax_dict
+
+
+def set_sales_tax(doc, method):
+	if not TAXJAR_CALCULATE_TAX:
+		return
+
+	if not doc.items:
+		return
+
+	# if the party is exempt from sales tax, then set all tax account heads to zero
+	sales_tax_exempted = hasattr(doc, "exempt_from_sales_tax") and doc.exempt_from_sales_tax \
+		or frappe.db.has_column("Customer", "exempt_from_sales_tax") and frappe.db.get_value("Customer", doc.customer, "exempt_from_sales_tax")
+
+	if sales_tax_exempted:
+		for tax in doc.taxes:
+			if tax.account_head == TAX_ACCOUNT_HEAD:
+				tax.tax_amount = 0
+				break
+
+		doc.run_method("calculate_taxes_and_totals")
+		return
+
+	tax_dict = get_tax_data(doc)
+
+	if not tax_dict:
+		# Remove existing tax rows if address is changed from a taxable state/country
+		setattr(doc, "taxes", [tax for tax in doc.taxes if tax.account_head != TAX_ACCOUNT_HEAD])
+		return
+
+	tax_data = validate_tax_request(tax_dict)
+
+	if tax_data is not None:
+		if not tax_data.amount_to_collect:
+			setattr(doc, "taxes", [tax for tax in doc.taxes if tax.account_head != TAX_ACCOUNT_HEAD])
+		elif tax_data.amount_to_collect > 0:
+			# Loop through tax rows for existing Sales Tax entry
+			# If none are found, add a row with the tax amount
+			for tax in doc.taxes:
+				if tax.account_head == TAX_ACCOUNT_HEAD:
+					tax.tax_amount = tax_data.amount_to_collect
+
+					doc.run_method("calculate_taxes_and_totals")
+					break
+			else:
+				doc.append("taxes", {
+					"charge_type": "Actual",
+					"description": "Sales Tax",
+					"account_head": TAX_ACCOUNT_HEAD,
+					"tax_amount": tax_data.amount_to_collect
+				})
+
+			doc.run_method("calculate_taxes_and_totals")
+
+
+def validate_tax_request(tax_dict):
+	"""Return the sales tax that should be collected for a given order."""
+
+	client = get_client()
+
+	if not client:
+		return
+
+	try:
+		tax_data = client.tax_for_order(tax_dict)
+	except taxjar.exceptions.TaxJarResponseError as err:
+		frappe.throw(_(sanitize_error_response(err)))
+	else:
+		return tax_data
+
+
+def get_company_address_details(doc):
+	"""Return default company address details"""
+
+	company_address = get_company_address(get_default_company()).company_address
+
+	if not company_address:
+		frappe.throw(_("Please set a default company address"))
+
+	company_address = frappe.get_doc("Address", company_address)
+	return company_address
+
+
+def get_shipping_address_details(doc):
+	"""Return customer shipping address details"""
+
+	if doc.shipping_address_name:
+		shipping_address = frappe.get_doc("Address", doc.shipping_address_name)
+	else:
+		shipping_address = get_company_address_details(doc)
+
+	return shipping_address
+
+
+def get_iso_3166_2_state_code(address):
+	country_code = frappe.db.get_value("Country", address.get("country"), "code")
+
+	error_message = _("""{0} is not a valid state! Check for typos or enter the ISO code for your state.""").format(address.get("state"))
+	state = address.get("state").upper().strip()
+
+	# The max length for ISO state codes is 3, excluding the country code
+	if len(state) <= 3:
+		# PyCountry returns state code as {country_code}-{state-code} (e.g. US-FL)
+		address_state = (country_code + "-" + state).upper()
+
+		states = pycountry.subdivisions.get(country_code=country_code.upper())
+		states = [pystate.code for pystate in states]
+
+		if address_state in states:
+			return state
+
+		frappe.throw(_(error_message))
+	else:
+		try:
+			lookup_state = pycountry.subdivisions.lookup(state)
+		except LookupError:
+			frappe.throw(_(error_message))
+		else:
+			return lookup_state.code.split('-')[1]
+
+
+def sanitize_error_response(response):
+	response = response.full_response.get("detail")
+	response = response.replace("_", " ")
+
+	sanitized_responses = {
+		"to zip": "Zipcode",
+		"to city": "City",
+		"to state": "State",
+		"to country": "Country"
+	}
+
+	for k, v in sanitized_responses.items():
+		response = response.replace(k, v)
+
+	return response
diff --git a/erpnext/healthcare/dashboard_chart/clinical_procedures/clinical_procedures.json b/erpnext/healthcare/dashboard_chart/clinical_procedures/clinical_procedures.json
new file mode 100644
index 0000000..a59f149
--- /dev/null
+++ b/erpnext/healthcare/dashboard_chart/clinical_procedures/clinical_procedures.json
@@ -0,0 +1,26 @@
+{
+ "chart_name": "Clinical Procedures",
+ "chart_type": "Group By",
+ "creation": "2020-07-14 18:17:54.601236",
+ "docstatus": 0,
+ "doctype": "Dashboard Chart",
+ "document_type": "Clinical Procedure",
+ "dynamic_filters_json": "[[\"Clinical Procedure\",\"company\",\"=\",\"frappe.defaults.get_user_default(\\\"Company\\\")\"]]",
+ "filters_json": "[[\"Clinical Procedure\",\"docstatus\",\"=\",\"1\",false]]",
+ "group_by_based_on": "procedure_template",
+ "group_by_type": "Count",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "last_synced_on": "2020-07-22 13:22:47.008622",
+ "modified": "2020-07-22 13:36:48.114479",
+ "modified_by": "Administrator",
+ "module": "Healthcare",
+ "name": "Clinical Procedures",
+ "number_of_groups": 0,
+ "owner": "Administrator",
+ "timeseries": 0,
+ "type": "Percentage",
+ "use_report_chart": 0,
+ "y_axis": []
+}
\ No newline at end of file
diff --git a/erpnext/healthcare/dashboard_chart/clinical_procedures_status/clinical_procedures_status.json b/erpnext/healthcare/dashboard_chart/clinical_procedures_status/clinical_procedures_status.json
new file mode 100644
index 0000000..6d560f7
--- /dev/null
+++ b/erpnext/healthcare/dashboard_chart/clinical_procedures_status/clinical_procedures_status.json
@@ -0,0 +1,26 @@
+{
+ "chart_name": "Clinical Procedure Status",
+ "chart_type": "Group By",
+ "creation": "2020-07-14 18:17:54.654325",
+ "docstatus": 0,
+ "doctype": "Dashboard Chart",
+ "document_type": "Clinical Procedure",
+ "dynamic_filters_json": "[[\"Clinical Procedure\",\"company\",\"=\",\"frappe.defaults.get_user_default(\\\"Company\\\")\"]]",
+ "filters_json": "[[\"Clinical Procedure\",\"docstatus\",\"=\",\"1\",false]]",
+ "group_by_based_on": "status",
+ "group_by_type": "Count",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "last_synced_on": "2020-07-22 13:22:46.691764",
+ "modified": "2020-07-22 13:40:17.215775",
+ "modified_by": "Administrator",
+ "module": "Healthcare",
+ "name": "Clinical Procedures Status",
+ "number_of_groups": 0,
+ "owner": "Administrator",
+ "timeseries": 0,
+ "type": "Pie",
+ "use_report_chart": 0,
+ "y_axis": []
+}
\ No newline at end of file
diff --git a/erpnext/healthcare/dashboard_chart/department_wise_patient_appointments/department_wise_patient_appointments.json b/erpnext/healthcare/dashboard_chart/department_wise_patient_appointments/department_wise_patient_appointments.json
new file mode 100644
index 0000000..b24bb34
--- /dev/null
+++ b/erpnext/healthcare/dashboard_chart/department_wise_patient_appointments/department_wise_patient_appointments.json
@@ -0,0 +1,25 @@
+{
+ "chart_name": "Department wise Patient Appointments",
+ "chart_type": "Custom",
+ "creation": "2020-07-17 11:25:37.190130",
+ "custom_options": "{\"colors\": [\"#7CD5FA\", \"#5F62F6\", \"#7544E2\", \"#EE5555\"], \"barOptions\": {\"stacked\": 1}, \"height\": 300}",
+ "docstatus": 0,
+ "doctype": "Dashboard Chart",
+ "dynamic_filters_json": "{\"company\":\"frappe.defaults.get_user_default(\\\"Company\\\")\"}",
+ "filters_json": "{}",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "last_synced_on": "2020-07-22 15:32:05.827566",
+ "modified": "2020-07-22 15:35:12.798035",
+ "modified_by": "Administrator",
+ "module": "Healthcare",
+ "name": "Department wise Patient Appointments",
+ "number_of_groups": 0,
+ "owner": "Administrator",
+ "source": "Department wise Patient Appointments",
+ "timeseries": 0,
+ "type": "Bar",
+ "use_report_chart": 0,
+ "y_axis": []
+}
\ No newline at end of file
diff --git a/erpnext/healthcare/dashboard_chart/diagnoses/diagnoses.json b/erpnext/healthcare/dashboard_chart/diagnoses/diagnoses.json
new file mode 100644
index 0000000..0195aac
--- /dev/null
+++ b/erpnext/healthcare/dashboard_chart/diagnoses/diagnoses.json
@@ -0,0 +1,25 @@
+{
+ "chart_name": "Diagnoses",
+ "chart_type": "Group By",
+ "creation": "2020-07-14 18:17:54.705698",
+ "docstatus": 0,
+ "doctype": "Dashboard Chart",
+ "document_type": "Patient Encounter Diagnosis",
+ "filters_json": "[]",
+ "group_by_based_on": "diagnosis",
+ "group_by_type": "Count",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "last_synced_on": "2020-07-22 13:22:47.895521",
+ "modified": "2020-07-22 13:43:32.369481",
+ "modified_by": "Administrator",
+ "module": "Healthcare",
+ "name": "Diagnoses",
+ "number_of_groups": 0,
+ "owner": "Administrator",
+ "timeseries": 0,
+ "type": "Percentage",
+ "use_report_chart": 0,
+ "y_axis": []
+}
\ No newline at end of file
diff --git a/erpnext/healthcare/dashboard_chart/in_patient_status/in_patient_status.json b/erpnext/healthcare/dashboard_chart/in_patient_status/in_patient_status.json
new file mode 100644
index 0000000..77b47c9
--- /dev/null
+++ b/erpnext/healthcare/dashboard_chart/in_patient_status/in_patient_status.json
@@ -0,0 +1,26 @@
+{
+ "chart_name": "In-Patient Status",
+ "chart_type": "Group By",
+ "creation": "2020-07-14 18:17:54.629199",
+ "docstatus": 0,
+ "doctype": "Dashboard Chart",
+ "document_type": "Inpatient Record",
+ "dynamic_filters_json": "[[\"Inpatient Record\",\"company\",\"=\",\"frappe.defaults.get_user_default(\\\"Company\\\")\"]]",
+ "filters_json": "[]",
+ "group_by_based_on": "status",
+ "group_by_type": "Count",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "last_synced_on": "2020-07-22 13:22:46.792131",
+ "modified": "2020-07-22 13:33:16.008150",
+ "modified_by": "Administrator",
+ "module": "Healthcare",
+ "name": "In-Patient Status",
+ "number_of_groups": 0,
+ "owner": "Administrator",
+ "timeseries": 0,
+ "type": "Bar",
+ "use_report_chart": 0,
+ "y_axis": []
+}
\ No newline at end of file
diff --git a/erpnext/healthcare/dashboard_chart/lab_tests/lab_tests.json b/erpnext/healthcare/dashboard_chart/lab_tests/lab_tests.json
new file mode 100644
index 0000000..0524835
--- /dev/null
+++ b/erpnext/healthcare/dashboard_chart/lab_tests/lab_tests.json
@@ -0,0 +1,26 @@
+{
+ "chart_name": "Lab Tests",
+ "chart_type": "Group By",
+ "creation": "2020-07-14 18:17:54.574903",
+ "docstatus": 0,
+ "doctype": "Dashboard Chart",
+ "document_type": "Lab Test",
+ "dynamic_filters_json": "[[\"Lab Test\",\"company\",\"=\",\"frappe.defaults.get_user_default(\\\"Company\\\")\"]]",
+ "filters_json": "[[\"Lab Test\",\"docstatus\",\"=\",\"1\",false]]",
+ "group_by_based_on": "template",
+ "group_by_type": "Count",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "last_synced_on": "2020-07-22 13:22:47.344055",
+ "modified": "2020-07-22 13:37:34.490129",
+ "modified_by": "Administrator",
+ "module": "Healthcare",
+ "name": "Lab Tests",
+ "number_of_groups": 0,
+ "owner": "Administrator",
+ "timeseries": 0,
+ "type": "Percentage",
+ "use_report_chart": 0,
+ "y_axis": []
+}
\ No newline at end of file
diff --git a/erpnext/healthcare/dashboard_chart/patient_appointments/patient_appointments.json b/erpnext/healthcare/dashboard_chart/patient_appointments/patient_appointments.json
new file mode 100644
index 0000000..19bfb72
--- /dev/null
+++ b/erpnext/healthcare/dashboard_chart/patient_appointments/patient_appointments.json
@@ -0,0 +1,27 @@
+{
+ "based_on": "appointment_datetime",
+ "chart_name": "Patient Appointments",
+ "chart_type": "Count",
+ "creation": "2020-07-14 18:17:54.525082",
+ "docstatus": 0,
+ "doctype": "Dashboard Chart",
+ "document_type": "Patient Appointment",
+ "dynamic_filters_json": "[[\"Patient Appointment\",\"company\",\"=\",\"frappe.defaults.get_user_default(\\\"Company\\\")\"]]",
+ "filters_json": "[[\"Patient Appointment\",\"status\",\"!=\",\"Cancelled\",false]]",
+ "idx": 0,
+ "is_public": 0,
+ "is_standard": 1,
+ "last_synced_on": "2020-07-22 13:22:46.830491",
+ "modified": "2020-07-22 13:38:02.254190",
+ "modified_by": "Administrator",
+ "module": "Healthcare",
+ "name": "Patient Appointments",
+ "number_of_groups": 0,
+ "owner": "Administrator",
+ "time_interval": "Daily",
+ "timeseries": 1,
+ "timespan": "Last Month",
+ "type": "Line",
+ "use_report_chart": 0,
+ "y_axis": []
+}
\ No newline at end of file
diff --git a/erpnext/healthcare/dashboard_chart/symptoms/symptoms.json b/erpnext/healthcare/dashboard_chart/symptoms/symptoms.json
new file mode 100644
index 0000000..8fc86a1
--- /dev/null
+++ b/erpnext/healthcare/dashboard_chart/symptoms/symptoms.json
@@ -0,0 +1,26 @@
+{
+ "chart_name": "Symptoms",
+ "chart_type": "Group By",
+ "creation": "2020-07-14 18:17:54.680852",
+ "docstatus": 0,
+ "doctype": "Dashboard Chart",
+ "document_type": "Patient Encounter Symptom",
+ "dynamic_filters_json": "",
+ "filters_json": "[]",
+ "group_by_based_on": "complaint",
+ "group_by_type": "Count",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "last_synced_on": "2020-07-22 13:22:47.296748",
+ "modified": "2020-07-22 13:40:59.655129",
+ "modified_by": "Administrator",
+ "module": "Healthcare",
+ "name": "Symptoms",
+ "number_of_groups": 0,
+ "owner": "Administrator",
+ "timeseries": 0,
+ "type": "Percentage",
+ "use_report_chart": 0,
+ "y_axis": []
+}
\ No newline at end of file
diff --git a/erpnext/healthcare/dashboard_fixtures.py b/erpnext/healthcare/dashboard_fixtures.py
deleted file mode 100644
index 94668a1..0000000
--- a/erpnext/healthcare/dashboard_fixtures.py
+++ /dev/null
@@ -1,245 +0,0 @@
-# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-import frappe
-import json
-from frappe import _
-
-def get_data():
-	return frappe._dict({
-		"dashboards": get_dashboards(),
-		"charts": get_charts(),
-		"number_cards": get_number_cards(),
-	})
-
-def get_company():
-	company = frappe.defaults.get_defaults().company
-	if company:
-		return company
-	else:
-		company = frappe.get_list("Company", limit=1)
-		if company:
-			return company[0].name
-	return None
-
-def get_dashboards():
-	return [{
-		"name": "Healthcare",
-		"dashboard_name": "Healthcare",
-		"charts": [
-			{ "chart": "Patient Appointments", "width": "Full"},
-			{ "chart": "In-Patient Status", "width": "Half"},
-			{ "chart": "Clinical Procedures Status", "width": "Half"},
-			{ "chart": "Lab Tests", "width": "Half"},
-			{ "chart": "Clinical Procedures", "width": "Half"},
-			{ "chart": "Symptoms", "width": "Half"},
-			{ "chart": "Diagnoses", "width": "Half"},
-			{ "chart": "Department wise Patient Appointments", "width": "Full"}
-		],
-		"cards": [
-			{ "card": "Total Patients" },
-			{ "card": "Total Patient Admitted" },
-			{ "card": "Open Appointments" },
-			{ "card": "Appointments to Bill" }
-		]
-	}]
-
-def get_charts():
-	company = get_company()
-	return [
-			{
-				"doctype": "Dashboard Chart",
-				"time_interval": "Daily",
-				"name": "Patient Appointments",
-				"chart_name": _("Patient Appointments"),
-				"timespan": "Last Month",
-				"filters_json": json.dumps([
-					["Patient Appointment", "company", "=", company, False],
-					["Patient Appointment", "status", "!=", "Cancelled"]
-				]),
-				"chart_type": "Count",
-				"timeseries": 1,
-				"based_on": "appointment_datetime",
-				"owner": "Administrator",
-				"document_type": "Patient Appointment",
-				"type": "Line",
-				"width": "Half"
-			},
-			{
-				"doctype": "Dashboard Chart",
-				"name": "Department wise Patient Appointments",
-				"chart_name": _("Department wise Patient Appointments"),
-				"chart_type": "Custom",
-				"source": "Department wise Patient Appointments",
-				"filters_json": json.dumps([]),
-				'is_public': 1,
-				"owner": "Administrator",
-				"type": "Bar",
-				"width": "Full",
-				"custom_options": json.dumps({
-					"colors": ["#7CD5FA", "#5F62F6", "#7544E2", "#EE5555"],
-					"barOptions":{
-						"stacked":1
-					},
-					"height": 300
-				})
-			},
-			{
-				"doctype": "Dashboard Chart",
-				"name": "Lab Tests",
-				"chart_name": _("Lab Tests"),
-				"chart_type": "Group By",
-				"document_type": "Lab Test",
-				"group_by_type": "Count",
-				"group_by_based_on": "template",
-				"filters_json": json.dumps([
-					["Lab Test", "company", "=", company, False],
-					["Lab Test", "docstatus", "=", 1]
-				]),
-				'is_public': 1,
-				"owner": "Administrator",
-				"type": "Percentage",
-				"width": "Half",
-			},
-			{
-				"doctype": "Dashboard Chart",
-				"name": "Clinical Procedures",
-				"chart_name": _("Clinical Procedures"),
-				"chart_type": "Group By",
-				"document_type": "Clinical Procedure",
-				"group_by_type": "Count",
-				"group_by_based_on": "procedure_template",
-				"filters_json": json.dumps([
-					["Clinical Procedure", "company", "=", company, False],
-					["Clinical Procedure", "docstatus", "=", 1]
-				]),
-				'is_public': 1,
-				"owner": "Administrator",
-				"type": "Percentage",
-				"width": "Half",
-			},
-			{
-				"doctype": "Dashboard Chart",
-				"name": "In-Patient Status",
-				"chart_name": _("In-Patient Status"),
-				"chart_type": "Group By",
-				"document_type": "Inpatient Record",
-				"group_by_type": "Count",
-				"group_by_based_on": "status",
-				"filters_json": json.dumps([
-					["Inpatient Record", "company", "=", company, False]
-				]),
-				'is_public': 1,
-				"owner": "Administrator",
-				"type": "Bar",
-				"width": "Half",
-			},
-			{
-				"doctype": "Dashboard Chart",
-				"name": "Clinical Procedures Status",
-				"chart_name": _("Clinical Procedure Status"),
-				"chart_type": "Group By",
-				"document_type": "Clinical Procedure",
-				"group_by_type": "Count",
-				"group_by_based_on": "status",
-				"filters_json": json.dumps([
-					["Clinical Procedure", "company", "=", company, False],
-					["Clinical Procedure", "docstatus", "=", 1]
-				]),
-				'is_public': 1,
-				"owner": "Administrator",
-				"type": "Pie",
-				"width": "Half",
-			},
-			{
-				"doctype": "Dashboard Chart",
-				"name": "Symptoms",
-				"chart_name": _("Symptoms"),
-				"chart_type": "Group By",
-				"document_type": "Patient Encounter Symptom",
-				"group_by_type": "Count",
-				"group_by_based_on": "complaint",
-				"filters_json": json.dumps([]),
-				'is_public': 1,
-				"owner": "Administrator",
-				"type": "Percentage",
-				"width": "Half",
-			},
-			{
-				"doctype": "Dashboard Chart",
-				"name": "Diagnoses",
-				"chart_name": _("Diagnoses"),
-				"chart_type": "Group By",
-				"document_type": "Patient Encounter Diagnosis",
-				"group_by_type": "Count",
-				"group_by_based_on": "diagnosis",
-				"filters_json": json.dumps([]),
-				'is_public': 1,
-				"owner": "Administrator",
-				"type": "Percentage",
-				"width": "Half",
-			}
-		]
-
-def get_number_cards():
-	company = get_company()
-	return [
-		{
-			"name": "Total Patients",
-			"label": _("Total Patients"),
-			"function": "Count",
-			"doctype": "Number Card",
-			"document_type": "Patient",
-			"filters_json": json.dumps(
-				[["Patient","status","=","Active",False]]
-			),
-			"is_public": 1,
-			"owner": "Administrator",
-			"show_percentage_stats": 1,
-			"stats_time_interval": "Daily"
-		},
-		{
-			"name": "Total Patients Admitted",
-			"label": _("Total Patients Admitted"),
-			"function": "Count",
-			"doctype": "Number Card",
-			"document_type": "Patient",
-			"filters_json": json.dumps(
-				[["Patient","inpatient_status","=","Admitted",False]]
-			),
-			"is_public": 1,
-			"owner": "Administrator",
-			"show_percentage_stats": 1,
-			"stats_time_interval": "Daily"
-		},
-		{
-			"name": "Open Appointments",
-			"label": _("Open Appointments"),
-			"function": "Count",
-			"doctype": "Number Card",
-			"document_type": "Patient Appointment",
-			"filters_json": json.dumps(
-				[["Patient Appointment","company","=",company,False],
-				["Patient Appointment","status","=","Open",False]]
-			),
-			"is_public": 1,
-			"owner": "Administrator",
-			"show_percentage_stats": 1,
-			"stats_time_interval": "Daily"
-		},
-		{
-			"name": "Appointments to Bill",
-			"label": _("Appointments To Bill"),
-			"function": "Count",
-			"doctype": "Number Card",
-			"document_type": "Patient Appointment",
-			"filters_json": json.dumps(
-				[["Patient Appointment","company","=",company,False],
-				["Patient Appointment","invoiced","=",0,False]]
-			),
-			"is_public": 1,
-			"owner": "Administrator",
-			"show_percentage_stats": 1,
-			"stats_time_interval": "Daily"
-		}
-	]
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/antibiotic/antibiotic.json b/erpnext/healthcare/doctype/antibiotic/antibiotic.json
index d481036..41a3e31 100644
--- a/erpnext/healthcare/doctype/antibiotic/antibiotic.json
+++ b/erpnext/healthcare/doctype/antibiotic/antibiotic.json
@@ -1,115 +1,151 @@
 {
- "allow_copy": 1, 
- "allow_guest_to_view": 0, 
- "allow_import": 1, 
- "allow_rename": 1, 
- "autoname": "field:antibiotic_name", 
- "beta": 1, 
- "creation": "2016-02-23 11:11:30.749731", 
- "custom": 0, 
- "docstatus": 0, 
- "doctype": "DocType", 
- "document_type": "Setup", 
- "editable_grid": 0, 
+ "allow_copy": 1,
+ "allow_events_in_timeline": 0,
+ "allow_guest_to_view": 0,
+ "allow_import": 1,
+ "allow_rename": 1,
+ "autoname": "field:antibiotic_name",
+ "beta": 1,
+ "creation": "2016-02-23 11:11:30.749731",
+ "custom": 0,
+ "docstatus": 0,
+ "doctype": "DocType",
+ "document_type": "Setup",
+ "editable_grid": 0,
  "fields": [
   {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "antibiotic_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": "Antibiotic 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, 
-   "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": "antibiotic_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": "Antibiotic 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": 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": "abbr",
+   "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": "Abbr",
+   "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": "2017-08-31 13:44:43.199657", 
- "modified_by": "Administrator", 
- "module": "Healthcare", 
- "name": "Antibiotic", 
- "name_case": "", 
- "owner": "Administrator", 
+ ],
+ "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-10-01 17:58:23.136498",
+ "modified_by": "Administrator",
+ "module": "Healthcare",
+ "name": "Antibiotic",
+ "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": "Healthcare Administrator", 
-   "set_user_permissions": 0, 
-   "share": 1, 
-   "submit": 0, 
+   "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": "Healthcare Administrator",
+   "set_user_permissions": 0,
+   "share": 1,
+   "submit": 0,
    "write": 1
-  }, 
+  },
   {
-   "amend": 0, 
-   "apply_user_permissions": 0, 
-   "cancel": 0, 
-   "create": 0, 
-   "delete": 0, 
-   "email": 1, 
-   "export": 1, 
-   "if_owner": 0, 
-   "import": 0, 
-   "permlevel": 0, 
-   "print": 1, 
-   "read": 1, 
-   "report": 1, 
-   "role": "Laboratory User", 
-   "set_user_permissions": 0, 
-   "share": 1, 
-   "submit": 0, 
+   "amend": 0,
+   "cancel": 0,
+   "create": 0,
+   "delete": 0,
+   "email": 1,
+   "export": 1,
+   "if_owner": 0,
+   "import": 0,
+   "permlevel": 0,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "Laboratory User",
+   "set_user_permissions": 0,
+   "share": 1,
+   "submit": 0,
    "write": 0
   }
- ], 
- "quick_entry": 1, 
- "read_only": 0, 
- "read_only_onload": 0, 
- "restrict_to_domain": "Healthcare", 
- "search_fields": "antibiotic_name", 
- "show_name_in_global_search": 0, 
- "sort_field": "modified", 
- "sort_order": "DESC", 
- "title_field": "antibiotic_name", 
- "track_changes": 0, 
- "track_seen": 0
+ ],
+ "quick_entry": 1,
+ "read_only": 0,
+ "read_only_onload": 0,
+ "restrict_to_domain": "Healthcare",
+ "search_fields": "antibiotic_name",
+ "show_name_in_global_search": 0,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "title_field": "antibiotic_name",
+ "track_changes": 0,
+ "track_seen": 0,
+ "track_views": 0
 }
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.json b/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.json
index eaf8d80..b1d62da 100644
--- a/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.json
+++ b/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.json
@@ -11,6 +11,7 @@
   "title",
   "appointment",
   "procedure_template",
+  "medical_code",
   "column_break_30",
   "company",
   "invoiced",
@@ -290,11 +291,19 @@
    "no_copy": 1,
    "print_hide": 1,
    "read_only": 1
+  },
+  {
+   "fetch_from": "procedure_template.medical_code",
+   "fieldname": "medical_code",
+   "fieldtype": "Link",
+   "label": "Medical Code",
+   "options": "Medical Code",
+   "read_only": 1
   }
  ],
  "is_submittable": 1,
  "links": [],
- "modified": "2020-04-27 21:36:23.796924",
+ "modified": "2020-06-29 14:28:11.779815",
  "modified_by": "Administrator",
  "module": "Healthcare",
  "name": "Clinical Procedure",
diff --git a/erpnext/healthcare/doctype/clinical_procedure_template/clinical_procedure_template.js b/erpnext/healthcare/doctype/clinical_procedure_template/clinical_procedure_template.js
index 16d4540..1ef110d 100644
--- a/erpnext/healthcare/doctype/clinical_procedure_template/clinical_procedure_template.js
+++ b/erpnext/healthcare/doctype/clinical_procedure_template/clinical_procedure_template.js
@@ -30,6 +30,16 @@
 		mark_change_in_item(frm);
 	},
 
+	medical_code: function(frm) {
+		frm.set_query("medical_code", function() {
+			return {
+				filters: {
+					medical_code_standard: frm.doc.medical_code_standard
+				}
+			};
+		});
+	},
+
 	refresh: function(frm) {
 		frm.fields_dict['items'].grid.set_column_disp('barcode', false);
 		frm.fields_dict['items'].grid.set_column_disp('batch_no', false);
diff --git a/erpnext/healthcare/doctype/clinical_procedure_template/clinical_procedure_template.json b/erpnext/healthcare/doctype/clinical_procedure_template/clinical_procedure_template.json
index 9cfd682..17ac7eb 100644
--- a/erpnext/healthcare/doctype/clinical_procedure_template/clinical_procedure_template.json
+++ b/erpnext/healthcare/doctype/clinical_procedure_template/clinical_procedure_template.json
@@ -21,6 +21,9 @@
   "is_billable",
   "rate",
   "medical_department",
+  "medical_coding_section",
+  "medical_code_standard",
+  "medical_code",
   "consumables",
   "consume_stock",
   "items",
@@ -46,7 +49,6 @@
    "fieldname": "item_code",
    "fieldtype": "Data",
    "label": "Item Code",
-   "options": "Item",
    "read_only_depends_on": "eval: !doc.__islocal ",
    "reqd": 1
   },
@@ -173,10 +175,29 @@
    "no_copy": 1,
    "options": "Item",
    "read_only": 1
+  },
+  {
+   "collapsible": 1,
+   "fieldname": "medical_coding_section",
+   "fieldtype": "Section Break",
+   "label": "Medical Coding"
+  },
+  {
+   "fieldname": "medical_code_standard",
+   "fieldtype": "Link",
+   "label": "Medical Code Standard",
+   "options": "Medical Code Standard"
+  },
+  {
+   "depends_on": "medical_code_standard",
+   "fieldname": "medical_code",
+   "fieldtype": "Link",
+   "label": "Medical Code",
+   "options": "Medical Code"
   }
  ],
  "links": [],
- "modified": "2020-02-28 14:16:13.184981",
+ "modified": "2020-06-29 14:12:27.158130",
  "modified_by": "Administrator",
  "module": "Healthcare",
  "name": "Clinical Procedure Template",
diff --git a/erpnext/healthcare/doctype/lab_test_groups/__init__.py b/erpnext/healthcare/doctype/descriptive_test_result/__init__.py
similarity index 100%
copy from erpnext/healthcare/doctype/lab_test_groups/__init__.py
copy to erpnext/healthcare/doctype/descriptive_test_result/__init__.py
diff --git a/erpnext/healthcare/doctype/descriptive_test_result/descriptive_test_result.json b/erpnext/healthcare/doctype/descriptive_test_result/descriptive_test_result.json
new file mode 100644
index 0000000..fcd3828
--- /dev/null
+++ b/erpnext/healthcare/doctype/descriptive_test_result/descriptive_test_result.json
@@ -0,0 +1,74 @@
+{
+ "actions": [],
+ "allow_copy": 1,
+ "beta": 1,
+ "creation": "2016-02-22 15:12:36.202380",
+ "doctype": "DocType",
+ "document_type": "Document",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "lab_test_particulars",
+  "result_value",
+  "allow_blank",
+  "template",
+  "require_result_value"
+ ],
+ "fields": [
+  {
+   "fieldname": "lab_test_particulars",
+   "fieldtype": "Data",
+   "ignore_xss_filter": 1,
+   "in_list_view": 1,
+   "label": "Particulars",
+   "read_only": 1
+  },
+  {
+   "depends_on": "eval:doc.require_result_value == 1",
+   "fieldname": "result_value",
+   "fieldtype": "Small Text",
+   "ignore_xss_filter": 1,
+   "in_list_view": 1,
+   "label": "Value"
+  },
+  {
+   "fieldname": "template",
+   "fieldtype": "Link",
+   "hidden": 1,
+   "label": "Template",
+   "options": "Lab Test Template",
+   "print_hide": 1,
+   "report_hide": 1
+  },
+  {
+   "default": "0",
+   "fieldname": "require_result_value",
+   "fieldtype": "Check",
+   "hidden": 1,
+   "label": "Require Result Value",
+   "print_hide": 1,
+   "read_only": 1,
+   "report_hide": 1
+  },
+  {
+   "default": "1",
+   "fieldname": "allow_blank",
+   "fieldtype": "Check",
+   "label": "Allow Blank",
+   "print_hide": 1,
+   "read_only": 1,
+   "report_hide": 1
+  }
+ ],
+ "istable": 1,
+ "links": [],
+ "modified": "2020-07-23 12:33:47.693065",
+ "modified_by": "Administrator",
+ "module": "Healthcare",
+ "name": "Descriptive Test Result",
+ "owner": "Administrator",
+ "permissions": [],
+ "restrict_to_domain": "Healthcare",
+ "sort_field": "modified",
+ "sort_order": "DESC"
+}
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/sensitivity_test_items/sensitivity_test_items.py b/erpnext/healthcare/doctype/descriptive_test_result/descriptive_test_result.py
similarity index 83%
copy from erpnext/healthcare/doctype/sensitivity_test_items/sensitivity_test_items.py
copy to erpnext/healthcare/doctype/descriptive_test_result/descriptive_test_result.py
index 35c8efd..7ccf6b5 100644
--- a/erpnext/healthcare/doctype/sensitivity_test_items/sensitivity_test_items.py
+++ b/erpnext/healthcare/doctype/descriptive_test_result/descriptive_test_result.py
@@ -5,5 +5,5 @@
 from __future__ import unicode_literals
 from frappe.model.document import Document
 
-class SensitivityTestItems(Document):
+class DescriptiveTestResult(Document):
 	pass
diff --git a/erpnext/healthcare/doctype/special_test_template/__init__.py b/erpnext/healthcare/doctype/descriptive_test_template/__init__.py
similarity index 100%
rename from erpnext/healthcare/doctype/special_test_template/__init__.py
rename to erpnext/healthcare/doctype/descriptive_test_template/__init__.py
diff --git a/erpnext/healthcare/doctype/descriptive_test_template/descriptive_test_template.json b/erpnext/healthcare/doctype/descriptive_test_template/descriptive_test_template.json
new file mode 100644
index 0000000..9ee8f4f
--- /dev/null
+++ b/erpnext/healthcare/doctype/descriptive_test_template/descriptive_test_template.json
@@ -0,0 +1,41 @@
+{
+ "actions": [],
+ "allow_copy": 1,
+ "beta": 1,
+ "creation": "2016-02-22 16:12:12.394200",
+ "doctype": "DocType",
+ "document_type": "Setup",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "particulars",
+  "allow_blank"
+ ],
+ "fields": [
+  {
+   "fieldname": "particulars",
+   "fieldtype": "Data",
+   "ignore_xss_filter": 1,
+   "in_list_view": 1,
+   "label": "Result Component"
+  },
+  {
+   "default": "0",
+   "fieldname": "allow_blank",
+   "fieldtype": "Check",
+   "in_list_view": 1,
+   "label": "Allow Blank"
+  }
+ ],
+ "istable": 1,
+ "links": [],
+ "modified": "2020-06-24 14:03:51.728863",
+ "modified_by": "Administrator",
+ "module": "Healthcare",
+ "name": "Descriptive Test Template",
+ "owner": "Administrator",
+ "permissions": [],
+ "restrict_to_domain": "Healthcare",
+ "sort_field": "modified",
+ "sort_order": "DESC"
+}
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/special_test_template/special_test_template.py b/erpnext/healthcare/doctype/descriptive_test_template/descriptive_test_template.py
similarity index 83%
copy from erpnext/healthcare/doctype/special_test_template/special_test_template.py
copy to erpnext/healthcare/doctype/descriptive_test_template/descriptive_test_template.py
index e4e0d5b..281f32d 100644
--- a/erpnext/healthcare/doctype/special_test_template/special_test_template.py
+++ b/erpnext/healthcare/doctype/descriptive_test_template/descriptive_test_template.py
@@ -5,5 +5,5 @@
 from __future__ import unicode_literals
 from frappe.model.document import Document
 
-class SpecialTestTemplate(Document):
+class DescriptiveTestTemplate(Document):
 	pass
diff --git a/erpnext/healthcare/doctype/healthcare_settings/healthcare_settings.json b/erpnext/healthcare/doctype/healthcare_settings/healthcare_settings.json
index 2f0115c..0104386 100644
--- a/erpnext/healthcare/doctype/healthcare_settings/healthcare_settings.json
+++ b/erpnext/healthcare/doctype/healthcare_settings/healthcare_settings.json
@@ -39,8 +39,8 @@
   "create_lab_test_on_si_submit",
   "create_sample_collection_for_lab_test",
   "column_break_34",
-  "employee_name_and_designation_in_print",
   "lab_test_approval_required",
+  "employee_name_and_designation_in_print",
   "custom_signature_in_print",
   "laboratory_sms_alerts",
   "sms_printed",
@@ -306,7 +306,7 @@
  ],
  "issingle": 1,
  "links": [],
- "modified": "2020-03-26 11:25:21.842092",
+ "modified": "2020-07-08 15:17:21.543218",
  "modified_by": "Administrator",
  "module": "Healthcare",
  "name": "Healthcare Settings",
diff --git a/erpnext/healthcare/doctype/lab_test/lab_test.js b/erpnext/healthcare/doctype/lab_test/lab_test.js
index bf1ecc8..8036c7d 100644
--- a/erpnext/healthcare/doctype/lab_test/lab_test.js
+++ b/erpnext/healthcare/doctype/lab_test/lab_test.js
@@ -1,49 +1,53 @@
 // Copyright (c) 2016, ESS and contributors
 // For license information, please see license.txt
 
-cur_frm.cscript.custom_refresh = function(doc) {
-	cur_frm.toggle_display("sb_sensitivity", doc.sensitivity_toggle=="1");
-	cur_frm.toggle_display("sb_special", doc.special_toggle=="1");
-	cur_frm.toggle_display("sb_normal", doc.normal_toggle=="1");
+cur_frm.cscript.custom_refresh = function (doc) {
+	cur_frm.toggle_display('sb_sensitivity', doc.sensitivity_toggle);
+	cur_frm.toggle_display('organisms_section', doc.descriptive_toggle);
+	cur_frm.toggle_display('sb_descriptive', doc.descriptive_toggle);
+	cur_frm.toggle_display('sb_normal', doc.normal_toggle);
 };
 
 frappe.ui.form.on('Lab Test', {
-	setup: function(frm) {
+	setup: function (frm) {
 		frm.get_field('normal_test_items').grid.editable_fields = [
-			{fieldname: 'lab_test_name', columns: 3},
-			{fieldname: 'lab_test_event', columns: 2},
-			{fieldname: 'result_value', columns: 2},
-			{fieldname: 'lab_test_uom', columns: 1},
-			{fieldname: 'normal_range', columns: 2}
+			{ fieldname: 'lab_test_name', columns: 3 },
+			{ fieldname: 'lab_test_event', columns: 2 },
+			{ fieldname: 'result_value', columns: 2 },
+			{ fieldname: 'lab_test_uom', columns: 1 },
+			{ fieldname: 'normal_range', columns: 2 }
 		];
-		frm.get_field('special_test_items').grid.editable_fields = [
-			{fieldname: 'lab_test_particulars', columns: 3},
-			{fieldname: 'result_value', columns: 7}
+		frm.get_field('descriptive_test_items').grid.editable_fields = [
+			{ fieldname: 'lab_test_particulars', columns: 3 },
+			{ fieldname: 'result_value', columns: 7 }
 		];
 	},
-	refresh :  function(frm){
+	refresh: function (frm) {
 		refresh_field('normal_test_items');
-		refresh_field('special_test_items');
-		if(frm.doc.__islocal){
+		refresh_field('descriptive_test_items');
+		if (frm.doc.__islocal) {
 			frm.add_custom_button(__('Get from Patient Encounter'), function () {
 				get_lab_test_prescribed(frm);
 			});
 		}
-		if(frm.doc.docstatus==1	&&	frm.doc.status!='Approved'	&&	frm.doc.status!='Rejected'	&&	frappe.defaults.get_default("lab_test_approval_required")	&&	frappe.user.has_role("LabTest Approver")){
-			frm.add_custom_button(__('Approve'), function() {
-				status_update(1,frm);
-			});
-			frm.add_custom_button(__('Reject'), function() {
-				status_update(0,frm);
-			});
+		if (frappe.defaults.get_default('lab_test_approval_required') && frappe.user.has_role('LabTest Approver')) {
+			if (frm.doc.docstatus === 1 && frm.doc.status !== 'Approved' && frm.doc.status !== 'Rejected') {
+				frm.add_custom_button(__('Approve'), function () {
+					status_update(1, frm);
+				});
+				frm.add_custom_button(__('Reject'), function () {
+					status_update(0, frm);
+				});
+			}
 		}
-		if(frm.doc.docstatus==1 && frm.doc.sms_sent==0){
-			frm.add_custom_button(__('Send SMS'), function() {
+
+		if (frm.doc.docstatus === 1 && frm.doc.sms_sent === 0 && frm.doc.status !== 'Rejected' ) {
+			frm.add_custom_button(__('Send SMS'), function () {
 				frappe.call({
-					method: "erpnext.healthcare.doctype.healthcare_settings.healthcare_settings.get_sms_text",
-					args:{doc: frm.doc.name},
-					callback: function(r) {
-						if(!r.exc) {
+					method: 'erpnext.healthcare.doctype.healthcare_settings.healthcare_settings.get_sms_text',
+					args: { doc: frm.doc.name },
+					callback: function (r) {
+						if (!r.exc) {
 							var emailed = r.message.emailed;
 							var printed = r.message.printed;
 							make_dialog(frm, emailed, printed);
@@ -53,246 +57,223 @@
 			});
 		}
 
-	},
-	onload: function (frm) {
-		frm.add_fetch("practitioner", "department", "department");
-		if(frm.doc.employee){
-			frappe.call({
-				method: "frappe.client.get",
-				args:{
-					doctype: "Employee",
-					name: frm.doc.employee
-				},
-				callback: function(arg){
-					frappe.model.set_value(frm.doctype,frm.docname,"employee_name", arg.message.employee_name);
-					frappe.model.set_value(frm.doctype,frm.docname,"employee_designation", arg.message.designation);
-				}
-			});
-		}
 	}
 });
 
-frappe.ui.form.on("Lab Test", "patient", function(frm) {
-	if(frm.doc.patient){
+frappe.ui.form.on('Lab Test', 'patient', function (frm) {
+	if (frm.doc.patient) {
 		frappe.call({
-			"method": "erpnext.healthcare.doctype.patient.patient.get_patient_detail",
-			args: {
-				patient: frm.doc.patient
-			},
+			'method': 'erpnext.healthcare.doctype.patient.patient.get_patient_detail',
+			args: { patient: frm.doc.patient },
 			callback: function (data) {
 				var age = null;
-				if(data.message.dob){
+				if (data.message.dob) {
 					age = calculate_age(data.message.dob);
 				}
-				frappe.model.set_value(frm.doctype,frm.docname, "patient_age", age);
-				frappe.model.set_value(frm.doctype,frm.docname, "patient_sex", data.message.sex);
-				frappe.model.set_value(frm.doctype,frm.docname, "email", data.message.email);
-				frappe.model.set_value(frm.doctype,frm.docname, "mobile", data.message.mobile);
-				frappe.model.set_value(frm.doctype,frm.docname, "report_preference", data.message.report_preference);
+				let values = {
+					'patient_age': age,
+					'patient_sex': data.message.sex,
+					'email': data.message.email,
+					'mobile': data.message.mobile,
+					'report_preference': data.message.report_preference
+				};
+				frm.set_value(values);
 			}
 		});
 	}
 });
 
-frappe.ui.form.on('Normal Test Items', {
-	normal_test_items_remove: function() {
-		frappe.msgprint(__("Not permitted, configure Lab Test Template as required"));
+frappe.ui.form.on('Normal Test Result', {
+	normal_test_items_remove: function () {
+		frappe.msgprint(__('Not permitted, configure Lab Test Template as required'));
 		cur_frm.reload_doc();
 	}
 });
 
-frappe.ui.form.on('Special Test Items', {
-	special_test_items_remove: function() {
-		frappe.msgprint(__("Not permitted, configure Lab Test Template as required"));
+frappe.ui.form.on('Descriptive Test Result', {
+	descriptive_test_items_remove: function () {
+		frappe.msgprint(__('Not permitted, configure Lab Test Template as required'));
 		cur_frm.reload_doc();
 	}
 });
 
-var status_update = function(approve,frm){
+var status_update = function (approve, frm) {
 	var doc = frm.doc;
 	var status = null;
-	if(approve == 1){
-		status = "Approved";
+	if (approve == 1) {
+		status = 'Approved';
 	}
 	else {
-		status = "Rejected";
+		status = 'Rejected';
 	}
 	frappe.call({
-		method: "erpnext.healthcare.doctype.lab_test.lab_test.update_status",
-		args: {status: status, name: doc.name},
-		callback: function(){
+		method: 'erpnext.healthcare.doctype.lab_test.lab_test.update_status',
+		args: { status: status, name: doc.name },
+		callback: function () {
 			cur_frm.reload_doc();
 		}
 	});
 };
 
-var get_lab_test_prescribed = function(frm){
-	if(frm.doc.patient){
+var get_lab_test_prescribed = function (frm) {
+	if (frm.doc.patient) {
 		frappe.call({
-			method:	"erpnext.healthcare.doctype.lab_test.lab_test.get_lab_test_prescribed",
-			args:	{patient: frm.doc.patient},
-			callback: function(r){
+			method: 'erpnext.healthcare.doctype.lab_test.lab_test.get_lab_test_prescribed',
+			args: { patient: frm.doc.patient },
+			callback: function (r) {
 				show_lab_tests(frm, r.message);
 			}
 		});
 	}
-	else{
-		frappe.msgprint(__("Please select a Patient to get Lab Tests"));
+	else {
+		frappe.msgprint(__('Please select Patient to get Lab Tests'));
 	}
 };
 
-var show_lab_tests = function(frm, result){
+var show_lab_tests = function (frm, lab_test_list) {
 	var d = new frappe.ui.Dialog({
-		title: __("Lab Tests"),
-		fields: [
-			{
-				fieldtype: "HTML", fieldname: "lab_test"
-			}
-		]
+		title: __('Lab Tests'),
+		fields: [{
+			fieldtype: 'HTML', fieldname: 'lab_test'
+		}]
 	});
 	var html_field = d.fields_dict.lab_test.$wrapper;
 	html_field.empty();
-	$.each(result, function(x, y){
-		var row = $(repl('<div class="col-xs-12" style="padding-top:12px; text-align:center;" >\
-		<div class="col-xs-2"> %(lab_test)s </div>\
-		<div class="col-xs-2"> %(encounter)s </div>\
-		<div class="col-xs-3"> %(practitioner)s </div>\
-		<div class="col-xs-3"> %(date)s </div>\
-		<div class="col-xs-1">\
-		<a data-name="%(name)s" data-lab-test="%(lab_test)s"\
-		data-encounter="%(encounter)s" data-practitioner="%(practitioner)s"\
-		data-invoiced="%(invoiced)s" href="#"><button class="btn btn-default btn-xs">Get Lab Tests\
-		</button></a></div></div>', {name:y[0], lab_test: y[1], encounter:y[2], invoiced:y[3], practitioner:y[4], date:y[5]})).appendTo(html_field);
-		row.find("a").click(function() {
-			frm.doc.template = $(this).attr("data-lab-test");
-			frm.doc.prescription = $(this).attr("data-name");
-			frm.doc.practitioner = $(this).attr("data-practitioner");
-			frm.set_df_property("template", "read_only", 1);
-			frm.set_df_property("patient", "read_only", 1);
-			frm.set_df_property("practitioner", "read_only", 1);
+	$.each(lab_test_list, function (x, y) {
+		var row = $(repl(
+			'<div class="col-xs-12" style="padding-top:12px;">\
+				<div class="col-xs-3"> %(lab_test)s </div>\
+				<div class="col-xs-4"> %(practitioner_name)s<br>%(encounter)s</div>\
+				<div class="col-xs-3"> %(date)s </div>\
+				<div class="col-xs-1">\
+					<a data-name="%(name)s" data-lab-test="%(lab_test)s"\
+					data-encounter="%(encounter)s" data-practitioner="%(practitioner)s"\
+					data-invoiced="%(invoiced)s" href="#"><button class="btn btn-default btn-xs">Get</button></a>\
+				</div>\
+			</div><hr>',
+			{ name: y[0], lab_test: y[1], encounter: y[2], invoiced: y[3], practitioner: y[4], practitioner_name: y[5], date: y[6] })
+		).appendTo(html_field);
+
+		row.find("a").click(function () {
+			frm.doc.template = $(this).attr('data-lab-test');
+			frm.doc.prescription = $(this).attr('data-name');
+			frm.doc.practitioner = $(this).attr('data-practitioner');
+			frm.set_df_property('template', 'read_only', 1);
+			frm.set_df_property('patient', 'read_only', 1);
+			frm.set_df_property('practitioner', 'read_only', 1);
 			frm.doc.invoiced = 0;
-			if($(this).attr("data-invoiced") == 1){
+			if ($(this).attr('data-invoiced') === 1) {
 				frm.doc.invoiced = 1;
 			}
-			refresh_field("invoiced");
-			refresh_field("template");
+			refresh_field('invoiced');
+			refresh_field('template');
 			d.hide();
 			return false;
 		});
 	});
-	if(!result.length){
-		var msg = __("No Lab Tests found for the Patient {0}", [frm.doc.patient_name.bold()]);
+	if (!lab_test_list.length) {
+		var msg = __('No Lab Tests found for the Patient {0}', [frm.doc.patient_name.bold()]);
 		html_field.empty();
-		$(repl('<div class="col-xs-12" style="padding-top:0px;" >%(msg)s</div>', {msg: msg})).appendTo(html_field);
+		$(repl('<div class="col-xs-12" style="padding-top:0px;" >%(msg)s</div>', { msg: msg })).appendTo(html_field);
 	}
 	d.show();
 };
 
-cur_frm.cscript.custom_before_submit =  function(doc) {
-	if(doc.normal_test_items){
-		for(let result in doc.normal_test_items){
-			if(!doc.normal_test_items[result].result_value	&&	doc.normal_test_items[result].require_result_value == 1){
-				frappe.msgprint(__("Please input all required Result Value(s)"));
-				throw("Error");
+cur_frm.cscript.custom_before_submit = function (doc) {
+	if (doc.normal_test_items) {
+		for (let result in doc.normal_test_items) {
+			if (!doc.normal_test_items[result].result_value && !doc.normal_test_items[result].allow_blank && doc.normal_test_items[result].require_result_value) {
+				frappe.throw(__('Please input all required result values'));
 			}
 		}
 	}
-	if(doc.special_test_items){
-		for(let result in doc.special_test_items){
-			if(!doc.special_test_items[result].result_value	&&	doc.special_test_items[result].require_result_value == 1){
-				frappe.msgprint(__("Please input all required Result Value(s)"));
-				throw("Error");
+	if (doc.descriptive_test_items) {
+		for (let result in doc.descriptive_test_items) {
+			if (!doc.descriptive_test_items[result].result_value && !doc.descriptive_test_items[result].allow_blank && doc.descriptive_test_items[result].require_result_value) {
+				frappe.throw(__('Please input all required result values'));
 			}
 		}
 	}
 };
 
-var make_dialog = function(frm, emailed, printed) {
+var make_dialog = function (frm, emailed, printed) {
 	var number = frm.doc.mobile;
 
 	var dialog = new frappe.ui.Dialog({
 		title: 'Send SMS',
 		width: 400,
 		fields: [
-			{fieldname:'sms_type', fieldtype:'Select', label:'Type', options:
-			['Emailed','Printed']},
-			{fieldname:'number', fieldtype:'Data', label:'Mobile Number', reqd:1},
-			{fieldname:'messages_label', fieldtype:'HTML'},
-			{fieldname:'messages', fieldtype:'HTML', reqd:1}
+			{ fieldname: 'sms_type', fieldtype: 'Select', label: 'Type', options: ['Emailed', 'Printed'] },
+			{ fieldname: 'number', fieldtype: 'Data', label: 'Mobile Number', reqd: 1 },
+			{ fieldname: 'message', fieldtype: 'Small Text', label: 'Message', reqd: 1 }
 		],
-		primary_action_label: __("Send"),
-		primary_action : function(){
+		primary_action_label: __('Send'),
+		primary_action: function () {
 			var values = dialog.fields_dict;
-			if(!values){
+			if (!values) {
 				return;
 			}
-			send_sms(values,frm);
+			send_sms(values, frm);
 			dialog.hide();
 		}
 	});
-	if(frm.doc.report_preference == "Email"){
+	if (frm.doc.report_preference == 'Print') {
 		dialog.set_values({
-			'sms_type': "Emailed",
-			'number': number
+			'sms_type': 'Printed',
+			'number': number,
+			'message': printed
 		});
-		dialog.fields_dict.messages_label.html("Message".bold());
-		dialog.fields_dict.messages.html(emailed);
-	}else{
+	} else {
 		dialog.set_values({
-			'sms_type': "Printed",
-			'number': number
+			'sms_type': 'Emailed',
+			'number': number,
+			'message': emailed
 		});
-		dialog.fields_dict.messages_label.html("Message".bold());
-		dialog.fields_dict.messages.html(printed);
 	}
 	var fd = dialog.fields_dict;
-	$(fd.sms_type.input).change(function(){
-		if(dialog.get_value('sms_type') == 'Emailed'){
+	$(fd.sms_type.input).change(function () {
+		if (dialog.get_value('sms_type') == 'Emailed') {
 			dialog.set_values({
-				'number': number
+				'number': number,
+				'message': emailed
 			});
-			fd.messages_label.html("Message".bold());
-			fd.messages.html(emailed);
-		}else{
+		} else {
 			dialog.set_values({
-				'number': number
+				'number': number,
+				'message': printed
 			});
-			fd.messages_label.html("Message".bold());
-			fd.messages.html(printed);
 		}
 	});
 	dialog.show();
 };
 
-var send_sms = function(v,frm){
-	var doc = frm.doc;
-	var number = v.number.last_value;
-	var messages = v.messages.wrapper.innerText;
+var send_sms = function (vals, frm) {
+	var number = vals.number.value;
+	var message = vals.message.last_value;
+
+	if (!number || !message) {
+		frappe.throw(__('Did not send SMS, missing patient mobile number or message content.'));
+	}
 	frappe.call({
-		method: "frappe.core.doctype.sms_settings.sms_settings.send_sms",
+		method: 'frappe.core.doctype.sms_settings.sms_settings.send_sms',
 		args: {
 			receiver_list: [number],
-			msg: messages
+			msg: message
 		},
-		callback: function(r) {
-			if(r.exc) {frappe.msgprint(r.exc); return; }
-			else{
-				frappe.call({
-					method: "erpnext.healthcare.doctype.lab_test.lab_test.update_lab_test_print_sms_email_status",
-					args: {print_sms_email: "sms_sent", name: doc.name},
-					callback: function(){
-						cur_frm.reload_doc();
-					}
-				});
+		callback: function (r) {
+			if (r.exc) {
+				frappe.msgprint(r.exc);
+			} else {
+				frm.reload_doc();
 			}
 		}
 	});
 };
 
-var calculate_age = function(birth) {
-	var	ageMS = Date.parse(Date()) - Date.parse(birth);
-	var	age = new Date();
+var calculate_age = function (dob) {
+	var ageMS = Date.parse(Date()) - Date.parse(dob);
+	var age = new Date();
 	age.setTime(ageMS);
-	var	years =  age.getFullYear() - 1970;
-	return  years + " Year(s) " + age.getMonth() + " Month(s) " + age.getDate() + " Day(s)";
+	var years = age.getFullYear() - 1970;
+	return years + ' Year(s) ' + age.getMonth() + ' Month(s) ' + age.getDate() + ' Day(s)';
 };
diff --git a/erpnext/healthcare/doctype/lab_test/lab_test.json b/erpnext/healthcare/doctype/lab_test/lab_test.json
index 17dc1ed..2eb8014 100644
--- a/erpnext/healthcare/doctype/lab_test/lab_test.json
+++ b/erpnext/healthcare/doctype/lab_test/lab_test.json
@@ -10,48 +10,63 @@
  "engine": "InnoDB",
  "field_order": [
   "naming_series",
+  "template",
+  "lab_test_name",
+  "lab_test_group",
+  "medical_code",
+  "department",
+  "column_break_26",
+  "company",
+  "status",
+  "submitted_date",
+  "result_date",
+  "approved_date",
+  "expected_result_date",
+  "expected_result_time",
+  "printed_on",
+  "invoiced",
+  "sb_first",
   "patient",
   "patient_name",
   "patient_age",
   "patient_sex",
+  "inpatient_record",
   "report_preference",
   "email",
   "mobile",
-  "practitioner",
   "c_b",
-  "inpatient_record",
-  "company",
-  "department",
-  "status",
-  "submitted_date",
-  "approved_date",
-  "sample",
-  "result_date",
+  "practitioner",
+  "practitioner_name",
+  "requesting_department",
   "employee",
   "employee_name",
   "employee_designation",
   "user",
-  "invoiced",
-  "sb_first",
-  "lab_test_name",
-  "column_break_26",
-  "template",
-  "lab_test_group",
+  "sample",
   "sb_normal",
+  "lab_test_html",
   "normal_test_items",
-  "sb_special",
-  "special_test_items",
+  "sb_descriptive",
+  "descriptive_test_items",
+  "organisms_section",
+  "organism_test_items",
   "sb_sensitivity",
   "sensitivity_test_items",
   "sb_comments",
   "lab_test_comment",
   "sb_customresult",
   "custom_result",
+  "worksheet_section",
+  "worksheet_instructions",
+  "result_legend_section",
+  "legend_print_position",
+  "result_legend",
+  "section_break_50",
   "email_sent",
   "sms_sent",
   "printed",
   "normal_toggle",
-  "special_toggle",
+  "descriptive_toggle",
   "sensitivity_toggle",
   "amended_from",
   "prescription"
@@ -88,7 +103,6 @@
    "fieldname": "patient",
    "fieldtype": "Link",
    "ignore_user_permissions": 1,
-   "in_list_view": 1,
    "in_standard_filter": 1,
    "label": "Patient",
    "options": "Patient",
@@ -119,6 +133,7 @@
    "label": "Gender",
    "options": "Gender",
    "print_hide": 1,
+   "read_only": 1,
    "report_hide": 1,
    "reqd": 1,
    "set_only_once": 1
@@ -127,11 +142,14 @@
    "fieldname": "practitioner",
    "fieldtype": "Link",
    "ignore_user_permissions": 1,
-   "label": "Healthcare Practitioner",
+   "in_list_view": 1,
+   "label": "Requesting Practitioner",
+   "no_copy": 1,
    "options": "Healthcare Practitioner",
    "search_index": 1
   },
   {
+   "fetch_from": "patient.email",
    "fieldname": "email",
    "fieldtype": "Data",
    "hidden": 1,
@@ -141,6 +159,7 @@
    "report_hide": 1
   },
   {
+   "fetch_from": "patient.mobile",
    "fieldname": "mobile",
    "fieldtype": "Data",
    "hidden": 1,
@@ -165,21 +184,23 @@
    "print_hide": 1
   },
   {
+   "fetch_from": "template.department",
    "fieldname": "department",
    "fieldtype": "Link",
    "ignore_user_permissions": 1,
    "in_standard_filter": 1,
    "label": "Department",
    "options": "Medical Department",
+   "read_only": 1,
    "search_index": 1
   },
   {
    "fieldname": "status",
    "fieldtype": "Select",
-   "hidden": 1,
    "label": "Status",
    "options": "Draft\nCompleted\nApproved\nRejected\nCancelled",
    "print_hide": 1,
+   "read_only": 1,
    "report_hide": 1,
    "search_index": 1
   },
@@ -211,15 +232,38 @@
    "report_hide": 1
   },
   {
+   "default": "Today",
+   "fieldname": "expected_result_date",
+   "fieldtype": "Date",
+   "hidden": 1,
+   "label": "Expected Result Date",
+   "read_only": 1
+  },
+  {
+   "fieldname": "expected_result_time",
+   "fieldtype": "Time",
+   "hidden": 1,
+   "label": "Expected Result Time",
+   "read_only": 1
+  },
+  {
    "fieldname": "result_date",
    "fieldtype": "Date",
+   "hidden": 1,
    "label": "Result Date",
    "search_index": 1
   },
   {
+   "allow_on_submit": 1,
+   "fieldname": "printed_on",
+   "fieldtype": "Datetime",
+   "label": "Printed on",
+   "read_only": 1
+  },
+  {
    "fieldname": "employee",
    "fieldtype": "Link",
-   "label": "Lab Technician",
+   "label": "Employee (Lab Technician)",
    "no_copy": 1,
    "options": "Employee",
    "print_hide": 1,
@@ -229,7 +273,7 @@
    "fetch_from": "employee.employee_name",
    "fieldname": "employee_name",
    "fieldtype": "Data",
-   "label": "Technician Name",
+   "label": "Lab Technician Name",
    "no_copy": 1,
    "print_hide": 1,
    "read_only": 1,
@@ -239,7 +283,7 @@
    "fetch_from": "employee.designation",
    "fieldname": "employee_designation",
    "fieldtype": "Data",
-   "label": "Designation",
+   "label": "Lab Technician Designation",
    "no_copy": 1,
    "print_hide": 1,
    "read_only": 1,
@@ -256,6 +300,7 @@
    "report_hide": 1
   },
   {
+   "fetch_from": "patient.report_preference",
    "fieldname": "report_preference",
    "fieldtype": "Data",
    "label": "Report Preference",
@@ -271,7 +316,6 @@
    "fieldname": "lab_test_name",
    "fieldtype": "Data",
    "in_list_view": 1,
-   "in_standard_filter": 1,
    "label": "Test Name",
    "no_copy": 1,
    "print_hide": 1,
@@ -280,13 +324,10 @@
    "search_index": 1
   },
   {
-   "fieldname": "column_break_26",
-   "fieldtype": "Column Break"
-  },
-  {
    "fieldname": "template",
    "fieldtype": "Link",
    "ignore_user_permissions": 1,
+   "in_standard_filter": 1,
    "label": "Test Template",
    "options": "Lab Test Template",
    "print_hide": 1,
@@ -304,33 +345,40 @@
    "report_hide": 1
   },
   {
+   "fetch_from": "template.medical_code",
+   "fieldname": "medical_code",
+   "fieldtype": "Link",
+   "label": "Medical Code",
+   "options": "Medical Code",
+   "read_only": 1
+  },
+  {
    "fieldname": "sb_normal",
    "fieldtype": "Section Break"
   },
   {
    "fieldname": "normal_test_items",
    "fieldtype": "Table",
-   "options": "Normal Test Items"
+   "options": "Normal Test Result",
+   "print_hide": 1
   },
   {
-   "fieldname": "sb_special",
+   "fieldname": "lab_test_html",
+   "fieldtype": "HTML"
+  },
+  {
+   "depends_on": "descriptive_toggle",
+   "fieldname": "organisms_section",
    "fieldtype": "Section Break"
   },
   {
-   "fieldname": "special_test_items",
-   "fieldtype": "Table",
-   "options": "Special Test Items",
-   "print_hide": 1,
-   "report_hide": 1
-  },
-  {
    "fieldname": "sb_sensitivity",
    "fieldtype": "Section Break"
   },
   {
    "fieldname": "sensitivity_test_items",
    "fieldtype": "Table",
-   "options": "Sensitivity Test Items",
+   "options": "Sensitivity Test Result",
    "print_hide": 1,
    "report_hide": 1
   },
@@ -342,7 +390,8 @@
    "fieldname": "lab_test_comment",
    "fieldtype": "Text",
    "ignore_xss_filter": 1,
-   "label": "Comments"
+   "label": "Comments",
+   "print_hide": 1
   },
   {
    "collapsible": 1,
@@ -354,7 +403,8 @@
    "fieldname": "custom_result",
    "fieldtype": "Text Editor",
    "ignore_xss_filter": 1,
-   "label": "Custom Result"
+   "label": "Custom Result",
+   "print_hide": 1
   },
   {
    "default": "0",
@@ -390,14 +440,6 @@
   },
   {
    "default": "0",
-   "fieldname": "special_toggle",
-   "fieldtype": "Check",
-   "hidden": 1,
-   "print_hide": 1,
-   "report_hide": 1
-  },
-  {
-   "default": "0",
    "fieldname": "sensitivity_toggle",
    "fieldtype": "Check",
    "hidden": 1,
@@ -424,11 +466,91 @@
    "print_hide": 1,
    "read_only": 1,
    "report_hide": 1
+  },
+  {
+   "fieldname": "column_break_26",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fetch_from": "practitioner.department",
+   "fieldname": "requesting_department",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "label": "Requesting Department",
+   "options": "Medical Department",
+   "read_only": 1
+  },
+  {
+   "fetch_from": "practitioner.practitioner_name",
+   "fieldname": "practitioner_name",
+   "fieldtype": "Data",
+   "label": "Requesting Practitioner",
+   "read_only": 1
+  },
+  {
+   "collapsible": 1,
+   "fieldname": "result_legend_section",
+   "fieldtype": "Section Break",
+   "label": "Result Legend Print"
+  },
+  {
+   "fieldname": "legend_print_position",
+   "fieldtype": "Select",
+   "label": "Print Position",
+   "options": "\nBottom\nTop\nBoth",
+   "print_hide": 1
+  },
+  {
+   "fieldname": "result_legend",
+   "fieldtype": "Text Editor",
+   "label": "Result Legend",
+   "print_hide": 1
+  },
+  {
+   "fieldname": "section_break_50",
+   "fieldtype": "Section Break"
+  },
+  {
+   "fieldname": "worksheet_instructions",
+   "fieldtype": "Text Editor",
+   "label": "Worksheet Instructions",
+   "print_hide": 1
+  },
+  {
+   "collapsible": 1,
+   "fieldname": "worksheet_section",
+   "fieldtype": "Section Break",
+   "label": "Worksheet Print"
+  },
+  {
+   "fieldname": "descriptive_test_items",
+   "fieldtype": "Table",
+   "options": "Descriptive Test Result",
+   "print_hide": 1,
+   "report_hide": 1
+  },
+  {
+   "fieldname": "sb_descriptive",
+   "fieldtype": "Section Break"
+  },
+  {
+   "default": "0",
+   "fieldname": "descriptive_toggle",
+   "fieldtype": "Check",
+   "hidden": 1,
+   "print_hide": 1,
+   "report_hide": 1
+  },
+  {
+   "fieldname": "organism_test_items",
+   "fieldtype": "Table",
+   "options": "Organism Test Result",
+   "print_hide": 1
   }
  ],
  "is_submittable": 1,
  "links": [],
- "modified": "2020-04-04 19:16:29.131168",
+ "modified": "2020-07-16 13:35:24.811062",
  "modified_by": "Administrator",
  "module": "Healthcare",
  "name": "Lab Test",
diff --git a/erpnext/healthcare/doctype/lab_test/lab_test.py b/erpnext/healthcare/doctype/lab_test/lab_test.py
index b2c5e6b..865f4a1 100644
--- a/erpnext/healthcare/doctype/lab_test/lab_test.py
+++ b/erpnext/healthcare/doctype/lab_test/lab_test.py
@@ -10,26 +10,30 @@
 
 class LabTest(Document):
 	def on_submit(self):
-		frappe.db.set_value(self.doctype,self.name,"submitted_date", getdate())
+		self.db_set('submitted_date', getdate())
+		self.db_set('status', 'Completed')
 		insert_lab_test_to_medical_record(self)
-		frappe.db.set_value("Lab Test", self.name, "status", "Completed")
 
 	def on_cancel(self):
 		delete_lab_test_from_medical_record(self)
-		frappe.db.set_value("Lab Test", self.name, "status", "Cancelled")
+		self.db_set('status', 'Cancelled')
 		self.reload()
 
+	def validate(self):
+		if not self.is_new():
+			self.set_secondary_uom_result()
+
 	def on_update(self):
-		if(self.sensitivity_test_items):
+		if self.sensitivity_test_items:
 			sensitivity = sorted(self.sensitivity_test_items, key=lambda x: x.antibiotic_sensitivity)
 			for i, item in enumerate(sensitivity):
-				item.idx = i+1
+				item.idx = i + 1
 			self.sensitivity_test_items = sensitivity
 
 	def after_insert(self):
-		if(self.prescription):
-			frappe.db.set_value("Lab Prescription", self.prescription, "lab_test_created", 1)
-			if frappe.db.get_value("Lab Prescription", self.prescription, 'invoiced') == 1:
+		if self.prescription:
+			frappe.db.set_value('Lab Prescription', self.prescription, 'lab_test_created', 1)
+			if frappe.db.get_value('Lab Prescription', self.prescription, 'invoiced'):
 				self.invoiced = True
 		if not self.lab_test_name and self.template:
 			self.load_test_from_template()
@@ -40,109 +44,110 @@
 		create_test_from_template(lab_test)
 		self.reload()
 
+	def set_secondary_uom_result(self):
+		for item in self.normal_test_items:
+			if item.result_value and item.secondary_uom and item.conversion_factor:
+				try:
+					item.secondary_uom_result = float(item.result_value) * float(item.conversion_factor)
+				except:
+					item.secondary_uom_result = ''
+					frappe.msgprint(_('Result for Secondary UOM not calculated for row #{0}'.format(item.idx)), title = _('Warning'))
+
+
 def create_test_from_template(lab_test):
-	template = frappe.get_doc("Lab Test Template", lab_test.template)
-	patient = frappe.get_doc("Patient", lab_test.patient)
+	template = frappe.get_doc('Lab Test Template', lab_test.template)
+	patient = frappe.get_doc('Patient', lab_test.patient)
 
 	lab_test.lab_test_name = template.lab_test_name
 	lab_test.result_date = getdate()
 	lab_test.department = template.department
 	lab_test.lab_test_group = template.lab_test_group
+	lab_test.legend_print_position = template.legend_print_position
+	lab_test.result_legend = template.result_legend
+	lab_test.worksheet_instructions = template.worksheet_instructions
 
 	lab_test = create_sample_collection(lab_test, template, patient, None)
 	lab_test = load_result_format(lab_test, template, None, None)
 
 @frappe.whitelist()
 def update_status(status, name):
-	frappe.db.sql("""update `tabLab Test` set status=%s, approved_date=%s where name = %s""", (status, getdate(), name))
-
-@frappe.whitelist()
-def update_lab_test_print_sms_email_status(print_sms_email, name):
-	frappe.db.set_value("Lab Test",name,print_sms_email,1)
+	if name and status:
+		frappe.db.set_value('Lab Test', name, {
+			'status': status,
+			'approved_date': getdate()
+		})
 
 @frappe.whitelist()
 def create_multiple(doctype, docname):
+	if not doctype or not docname:
+		frappe.throw(_('Sales Invoice or Patient Encounter is required to create Lab Tests'), title=_('Insufficient Data'))
+
 	lab_test_created = False
-	if doctype == "Sales Invoice":
+	if doctype == 'Sales Invoice':
 		lab_test_created = create_lab_test_from_invoice(docname)
-	elif doctype == "Patient Encounter":
+	elif doctype == 'Patient Encounter':
 		lab_test_created = create_lab_test_from_encounter(docname)
 
 	if lab_test_created:
-		frappe.msgprint(_("Lab Test(s) {0} created".format(lab_test_created)))
+		frappe.msgprint(_('Lab Test(s) {0} created'.format(lab_test_created)))
 	else:
-		frappe.msgprint(_("No Lab Tests created"))
+		frappe.msgprint(_('No Lab Tests created'))
 
-def create_lab_test_from_encounter(encounter_id):
+def create_lab_test_from_encounter(encounter):
 	lab_test_created = False
-	encounter = frappe.get_doc("Patient Encounter", encounter_id)
+	encounter = frappe.get_doc('Patient Encounter', encounter)
 
-	lab_test_ids = frappe.db.sql("""select lp.name, lp.lab_test_code, lp.invoiced
-	from `tabPatient Encounter` et, `tabLab Prescription` lp
-	where et.patient=%s and lp.parent=%s and
-	lp.parent=et.name and lp.lab_test_created=0 and et.docstatus=1""", (encounter.patient, encounter_id))
-
-	if lab_test_ids:
-		patient = frappe.get_doc("Patient", encounter.patient)
-		for lab_test_id in lab_test_ids:
-			template = get_lab_test_template(lab_test_id[1])
-			if template:
-				lab_test = create_lab_test_doc(lab_test_id[2], encounter.practitioner, patient, template, encounter.company)
-				lab_test.save(ignore_permissions = True)
-				frappe.db.set_value("Lab Prescription", lab_test_id[0], "lab_test_created", 1)
-				if not lab_test_created:
-					lab_test_created = lab_test.name
-				else:
-					lab_test_created += ", "+lab_test.name
+	if encounter and encounter.lab_test_prescription:
+		patient = frappe.get_doc('Patient', encounter.patient)
+		for item in encounter.lab_test_prescription:
+			if not item.lab_test_created:
+				template = get_lab_test_template(item.lab_test_code)
+				if template:
+					lab_test = create_lab_test_doc(item.invoiced, encounter.practitioner, patient, template, encounter.company)
+					lab_test.save(ignore_permissions = True)
+					frappe.db.set_value('Lab Prescription', item.name, 'lab_test_created', 1)
+					if not lab_test_created:
+						lab_test_created = lab_test.name
+					else:
+						lab_test_created += ', ' + lab_test.name
 	return lab_test_created
 
 
-def create_lab_test_from_invoice(invoice_name):
+def create_lab_test_from_invoice(sales_invoice):
 	lab_tests_created = False
-	invoice = frappe.get_doc("Sales Invoice", invoice_name)
-	if invoice.patient:
-		patient = frappe.get_doc("Patient", invoice.patient)
+	invoice = frappe.get_doc('Sales Invoice', sales_invoice)
+	if invoice and invoice.patient:
+		patient = frappe.get_doc('Patient', invoice.patient)
 		for item in invoice.items:
 			lab_test_created = 0
-			if item.reference_dt == "Lab Prescription":
-				lab_test_created = frappe.db.get_value("Lab Prescription", item.reference_dn, "lab_test_created")
-			elif item.reference_dt == "Lab Test":
+			if item.reference_dt == 'Lab Prescription':
+				lab_test_created = frappe.db.get_value('Lab Prescription', item.reference_dn, 'lab_test_created')
+			elif item.reference_dt == 'Lab Test':
 				lab_test_created = 1
 			if lab_test_created != 1:
 				template = get_lab_test_template(item.item_code)
 				if template:
 					lab_test = create_lab_test_doc(True, invoice.ref_practitioner, patient, template, invoice.company)
-					if item.reference_dt == "Lab Prescription":
+					if item.reference_dt == 'Lab Prescription':
 						lab_test.prescription = item.reference_dn
 					lab_test.save(ignore_permissions = True)
-					if item.reference_dt != "Lab Prescription":
-						frappe.db.set_value("Sales Invoice Item", item.name, "reference_dt", "Lab Test")
-						frappe.db.set_value("Sales Invoice Item", item.name, "reference_dn", lab_test.name)
+					if item.reference_dt != 'Lab Prescription':
+						frappe.db.set_value('Sales Invoice Item', item.name, 'reference_dt', 'Lab Test')
+						frappe.db.set_value('Sales Invoice Item', item.name, 'reference_dn', lab_test.name)
 					if not lab_tests_created:
 						lab_tests_created = lab_test.name
 					else:
-						lab_tests_created += ", " + lab_test.name
+						lab_tests_created += ', ' + lab_test.name
 	return lab_tests_created
 
 def get_lab_test_template(item):
-	template_id = check_template_exists(item)
+	template_id = frappe.db.exists('Lab Test Template', {'item': item})
 	if template_id:
-		return frappe.get_doc("Lab Test Template", template_id)
-	return False
-
-def check_template_exists(item):
-	template_exists = frappe.db.exists(
-		"Lab Test Template",
-		{
-			'item': item
-		}
-	)
-	if template_exists:
-		return template_exists
+		return frappe.get_doc('Lab Test Template', template_id)
 	return False
 
 def create_lab_test_doc(invoiced, practitioner, patient, template, company):
-	lab_test = frappe.new_doc("Lab Test")
+	lab_test = frappe.new_doc('Lab Test')
 	lab_test.invoiced = invoiced
 	lab_test.practitioner = practitioner
 	lab_test.patient = patient.name
@@ -159,63 +164,71 @@
 	return lab_test
 
 def create_normals(template, lab_test):
-	lab_test.normal_toggle = "1"
-	normal = lab_test.append("normal_test_items")
+	lab_test.normal_toggle = 1
+	normal = lab_test.append('normal_test_items')
 	normal.lab_test_name = template.lab_test_name
 	normal.lab_test_uom = template.lab_test_uom
+	normal.secondary_uom = template.secondary_uom
+	normal.conversion_factor = template.conversion_factor
 	normal.normal_range = template.lab_test_normal_range
 	normal.require_result_value = 1
+	normal.allow_blank = 0
 	normal.template = template.name
 
 def create_compounds(template, lab_test, is_group):
-	lab_test.normal_toggle = "1"
+	lab_test.normal_toggle = 1
 	for normal_test_template in template.normal_test_templates:
-		normal = lab_test.append("normal_test_items")
+		normal = lab_test.append('normal_test_items')
 		if is_group:
 			normal.lab_test_event = normal_test_template.lab_test_event
 		else:
 			normal.lab_test_name = normal_test_template.lab_test_event
 
 		normal.lab_test_uom = normal_test_template.lab_test_uom
+		normal.secondary_uom = normal_test_template.secondary_uom
+		normal.conversion_factor = normal_test_template.conversion_factor
 		normal.normal_range = normal_test_template.normal_range
 		normal.require_result_value = 1
+		normal.allow_blank = normal_test_template.allow_blank
 		normal.template = template.name
 
-def create_specials(template, lab_test):
-	lab_test.special_toggle = "1"
-	if(template.sensitivity):
-		lab_test.sensitivity_toggle = "1"
-	for special_test_template in template.special_test_template:
-		special = lab_test.append("special_test_items")
-		special.lab_test_particulars = special_test_template.particulars
-		special.require_result_value = 1
-		special.template = template.name
+def create_descriptives(template, lab_test):
+	lab_test.descriptive_toggle = 1
+	if template.sensitivity:
+		lab_test.sensitivity_toggle = 1
+	for descriptive_test_template in template.descriptive_test_templates:
+		descriptive = lab_test.append('descriptive_test_items')
+		descriptive.lab_test_particulars = descriptive_test_template.particulars
+		descriptive.require_result_value = 1
+		descriptive.allow_blank = descriptive_test_template.allow_blank
+		descriptive.template = template.name
 
 def create_sample_doc(template, patient, invoice, company = None):
 	if template.sample:
 		sample_exists = frappe.db.exists({
-			"doctype": "Sample Collection",
-			"patient": patient.name,
-			"docstatus": 0,
-			"sample": template.sample
+			'doctype': 'Sample Collection',
+			'patient': patient.name,
+			'docstatus': 0,
+			'sample': template.sample
 		})
 		if sample_exists:
-			# update Sample Collection by adding quantity
-			sample_collection = frappe.get_doc("Sample Collection", sample_exists[0][0])
+			# Update Sample Collection by adding quantity
+			sample_collection = frappe.get_doc('Sample Collection', sample_exists[0][0])
 			quantity = int(sample_collection.sample_qty) + int(template.sample_qty)
 			if template.sample_details:
-				sample_details = sample_collection.sample_details + "\n==============\n" + _("Test: ")
-				sample_details += (template.get("lab_test_name") or template.get("template")) +	"\n"
-				sample_details += _("Collection Details: ") + "\n\t" + template.sample_details
+				sample_details = sample_collection.sample_details + '\n-\n' + _('Test: ')
+				sample_details += (template.get('lab_test_name') or template.get('template')) +	'\n'
+				sample_details += _('Collection Details: ') + '\n\t' + template.sample_details
+				frappe.db.set_value('Sample Collection', sample_collection.name, 'sample_details', sample_details)
 
-				frappe.db.set_value("Sample Collection", sample_collection.name, "sample_details", sample_details)
-			frappe.db.set_value("Sample Collection", sample_collection.name, "sample_qty", quantity)
+			frappe.db.set_value('Sample Collection', sample_collection.name, 'sample_qty', quantity)
 
 		else:
-			#create Sample Collection for template, copy vals from Invoice
-			sample_collection = frappe.new_doc("Sample Collection")
-			if(invoice):
+			# Create Sample Collection for template, copy vals from Invoice
+			sample_collection = frappe.new_doc('Sample Collection')
+			if invoice:
 				sample_collection.invoiced = True
+
 			sample_collection.patient = patient.name
 			sample_collection.patient_age = patient.get_age()
 			sample_collection.patient_sex = patient.sex
@@ -224,125 +237,146 @@
 			sample_collection.sample_qty = template.sample_qty
 			sample_collection.company = company
 
-			if(template.sample_details):
-				sample_collection.sample_details = "Test :" + (template.get("lab_test_name") or template.get("template")) +"\n"+"Collection Detials:\n\t"+template.sample_details
+			if template.sample_details:
+				sample_collection.sample_details = 'Test :' + (template.get('lab_test_name') or template.get('template')) + '\n' + 'Collection Detials:\n\t' + template.sample_details
 			sample_collection.save(ignore_permissions=True)
 
 		return sample_collection
 
 def create_sample_collection(lab_test, template, patient, invoice):
-	if(frappe.db.get_value("Healthcare Settings", None, "create_sample_collection_for_lab_test") == "1"):
+	if frappe.get_cached_value('Healthcare Settings', None, 'create_sample_collection_for_lab_test'):
 		sample_collection = create_sample_doc(template, patient, invoice, lab_test.company)
-		if(sample_collection):
+		if sample_collection:
 			lab_test.sample = sample_collection.name
+
 	return lab_test
 
 def load_result_format(lab_test, template, prescription, invoice):
-	if(template.lab_test_template_type == 'Single'):
+	if template.lab_test_template_type == 'Single':
 		create_normals(template, lab_test)
-	elif(template.lab_test_template_type == 'Compound'):
+	elif template.lab_test_template_type == 'Compound':
 		create_compounds(template, lab_test, False)
-	elif(template.lab_test_template_type == 'Descriptive'):
-		create_specials(template, lab_test)
-	elif(template.lab_test_template_type == 'Grouped'):
-		#iterate for each template in the group and create one result for all.
+	elif template.lab_test_template_type == 'Descriptive':
+		create_descriptives(template, lab_test)
+	elif template.lab_test_template_type == 'Grouped':
+		# Iterate for each template in the group and create one result for all.
 		for lab_test_group in template.lab_test_groups:
-			#template_in_group = None
-			if(lab_test_group.lab_test_template):
-				template_in_group = frappe.get_doc("Lab Test Template",
+			# Template_in_group = None
+			if lab_test_group.lab_test_template:
+				template_in_group = frappe.get_doc('Lab Test Template',
 								lab_test_group.lab_test_template)
-				if(template_in_group):
-					if(template_in_group.lab_test_template_type == 'Single'):
+				if template_in_group:
+					if template_in_group.lab_test_template_type == 'Single':
 						create_normals(template_in_group, lab_test)
-					elif(template_in_group.lab_test_template_type == 'Compound'):
-						normal_heading = lab_test.append("normal_test_items")
+					elif template_in_group.lab_test_template_type == 'Compound':
+						normal_heading = lab_test.append('normal_test_items')
 						normal_heading.lab_test_name = template_in_group.lab_test_name
 						normal_heading.require_result_value = 0
+						normal_heading.allow_blank = 1
 						normal_heading.template = template_in_group.name
 						create_compounds(template_in_group, lab_test, True)
-					elif(template_in_group.lab_test_template_type == 'Descriptive'):
-						special_heading = lab_test.append("special_test_items")
-						special_heading.lab_test_name = template_in_group.lab_test_name
-						special_heading.require_result_value = 0
-						special_heading.template = template_in_group.name
-						create_specials(template_in_group, lab_test)
-			else:
-				normal = lab_test.append("normal_test_items")
+					elif template_in_group.lab_test_template_type == 'Descriptive':
+						descriptive_heading = lab_test.append('descriptive_test_items')
+						descriptive_heading.lab_test_name = template_in_group.lab_test_name
+						descriptive_heading.require_result_value = 0
+						descriptive_heading.allow_blank = 1
+						descriptive_heading.template = template_in_group.name
+						create_descriptives(template_in_group, lab_test)
+			else: # Lab Test Group - Add New Line
+				normal = lab_test.append('normal_test_items')
 				normal.lab_test_name = lab_test_group.group_event
 				normal.lab_test_uom = lab_test_group.group_test_uom
+				normal.secondary_uom = lab_test_group.secondary_uom
+				normal.conversion_factor = lab_test_group.conversion_factor
 				normal.normal_range = lab_test_group.group_test_normal_range
+				normal.allow_blank = lab_test_group.allow_blank
 				normal.require_result_value = 1
 				normal.template = template.name
-	if(template.lab_test_template_type != 'No Result'):
-		if(prescription):
+	if template.lab_test_template_type != 'No Result':
+		if prescription:
 			lab_test.prescription = prescription
-			if(invoice):
-				frappe.db.set_value("Lab Prescription", prescription, "invoiced", True)
-		lab_test.save(ignore_permissions=True) # insert the result
+			if invoice:
+				frappe.db.set_value('Lab Prescription', prescription, 'invoiced', True)
+		lab_test.save(ignore_permissions=True) # Insert the result
 		return lab_test
 
 @frappe.whitelist()
 def get_employee_by_user_id(user_id):
-	emp_id = frappe.db.get_value("Employee",{"user_id":user_id})
-	employee = frappe.get_doc("Employee",emp_id)
+	emp_id = frappe.db.get_value('Employee', { 'user_id': user_id })
+	employee = frappe.get_doc('Employee', emp_id)
 	return employee
 
 def insert_lab_test_to_medical_record(doc):
 	table_row = False
 	subject = cstr(doc.lab_test_name)
 	if doc.practitioner:
-		subject += frappe.bold(_("Healthcare Practitioner: "))+ doc.practitioner + "<br>"
+		subject += frappe.bold(_('Healthcare Practitioner: '))+ doc.practitioner + '<br>'
 	if doc.normal_test_items:
 		item = doc.normal_test_items[0]
-		comment = ""
+		comment = ''
 		if item.lab_test_comment:
 			comment = str(item.lab_test_comment)
-		table_row = frappe.bold(_("Lab Test Conducted: ")) + item.lab_test_name
+		table_row = frappe.bold(_('Lab Test Conducted: ')) + item.lab_test_name
 
 		if item.lab_test_event:
-			table_row += frappe.bold(_("Lab Test Event: ")) + item.lab_test_event
+			table_row += frappe.bold(_('Lab Test Event: ')) + item.lab_test_event
 
 		if item.result_value:
-			table_row += " " + frappe.bold(_("Lab Test Result: ")) + 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]
+	elif doc.descriptive_test_items:
+		item = doc.descriptive_test_items[0]
 
 		if item.lab_test_particulars and item.result_value:
-			table_row = item.lab_test_particulars +" "+ item.result_value
+			table_row = item.lab_test_particulars + ' ' + item.result_value
 
 	elif doc.sensitivity_test_items:
 		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 = frappe.new_doc('Patient Medical Record')
 	medical_record.patient = doc.patient
 	medical_record.subject = subject
-	medical_record.status = "Open"
+	medical_record.status = 'Open'
 	medical_record.communication_date = doc.result_date
-	medical_record.reference_doctype = "Lab Test"
+	medical_record.reference_doctype = 'Lab Test'
 	medical_record.reference_name = doc.name
 	medical_record.reference_owner = doc.owner
-	medical_record.save(ignore_permissions=True)
+	medical_record.save(ignore_permissions = True)
 
 def delete_lab_test_from_medical_record(self):
-	medical_record_id = frappe.db.sql("select name from `tabPatient Medical Record` where reference_name=%s",(self.name))
+	medical_record_id = frappe.db.sql('select name from `tabPatient Medical Record` where reference_name= %s', (self.name))
 
 	if medical_record_id and medical_record_id[0][0]:
-		frappe.delete_doc("Patient Medical Record", medical_record_id[0][0])
+		frappe.delete_doc('Patient Medical Record', medical_record_id[0][0])
 
 @frappe.whitelist()
 def get_lab_test_prescribed(patient):
-	return frappe.db.sql("""select cp.name, cp.lab_test_code, cp.parent, cp.invoiced, ct.practitioner, ct.encounter_date from `tabPatient Encounter` ct,
-	`tabLab Prescription` cp where ct.patient=%s and cp.parent=ct.name and cp.lab_test_created=0""", (patient))
+	return frappe.db.sql(
+		'''
+			select
+				lp.name,
+				lp.lab_test_code,
+				lp.parent,
+				lp.invoiced,
+				pe.practitioner,
+				pe.practitioner_name,
+				pe.encounter_date
+			from
+				`tabPatient Encounter` pe, `tabLab Prescription` lp
+			where
+				pe.patient=%s
+				and lp.parent=pe.name
+				and lp.lab_test_created=0
+		''', (patient))
diff --git a/erpnext/healthcare/doctype/lab_test/lab_test_list.js b/erpnext/healthcare/doctype/lab_test/lab_test_list.js
index 1f6a12f..6783bb3 100644
--- a/erpnext/healthcare/doctype/lab_test/lab_test_list.js
+++ b/erpnext/healthcare/doctype/lab_test/lab_test_list.js
@@ -2,57 +2,63 @@
 (c) ESS 2015-16
 */
 frappe.listview_settings['Lab Test'] = {
-	add_fields: ["name", "status", "invoiced"],
-	filters:[["docstatus","=","0"]],
-	get_indicator: function(doc) {
-		if(doc.status=="Approved"){
-			return [__("Approved"), "green", "status,=,Approved"];
+	add_fields: ['name', 'status', 'invoiced'],
+	filters: [['docstatus', '=', '0']],
+	get_indicator: function (doc) {
+		if (doc.status == 'Approved') {
+			return [__('Approved'), 'green', 'status, = ,Approved'];
 		}
-		if(doc.status=="Rejected"){
-			return [__("Rejected"), "yellow", "status,=,Rejected"];
+		if (doc.status == 'Rejected') {
+			return [__('Rejected'), 'orange', 'status, =, Rejected'];
 		}
 	},
-	onload: function(listview) {
-		listview.page.add_menu_item(__("Create Multiple"), function() {
+	onload: function (listview) {
+		listview.page.add_menu_item(__('Create Multiple'), function () {
 			create_multiple_dialog(listview);
 		});
 	}
 };
 
-var create_multiple_dialog = function(listview){
+var create_multiple_dialog = function (listview) {
 	var dialog = new frappe.ui.Dialog({
 		title: 'Create Multiple Lab Test',
 		width: 100,
 		fields: [
-			{fieldtype: "Link", label: "Patient", fieldname: "patient", options: "Patient", reqd: 1},
-			{fieldtype: "Select", label: "Invoice / Patient Encounter", fieldname: "doctype",
-				options: "\nSales Invoice\nPatient Encounter", reqd: 1},
-			{fieldtype: "Dynamic Link", fieldname: "docname", options: "doctype", reqd: 1,
-				get_query: function(){
+			{ fieldtype: 'Link', label: 'Patient', fieldname: 'patient', options: 'Patient', reqd: 1 },
+			{
+				fieldtype: 'Select', label: 'Invoice / Patient Encounter', fieldname: 'doctype',
+				options: '\nSales Invoice\nPatient Encounter', reqd: 1
+			},
+			{
+				fieldtype: 'Dynamic Link', fieldname: 'docname', options: 'doctype', reqd: 1,
+				get_query: function () {
 					return {
 						filters: {
-							"patient": dialog.get_value("patient"),
-							"docstatus": 1
+							'patient': dialog.get_value('patient'),
+							'docstatus': 1
 						}
 					};
 				}
 			}
 		],
-		primary_action_label: __("Create Lab Test"),
-		primary_action : function(){
+		primary_action_label: __('Create Lab Test'),
+		primary_action: function () {
 			frappe.call({
 				method: 'erpnext.healthcare.doctype.lab_test.lab_test.create_multiple',
-				args:{
-					'doctype': dialog.get_value("doctype"),
-					'docname': dialog.get_value("docname")
+				args: {
+					'doctype': dialog.get_value('doctype'),
+					'docname': dialog.get_value('docname')
 				},
-				callback: function(data) {
-					if(!data.exc){
+				callback: function (data) {
+					if (!data.exc) {
+						if (!data.message) {
+							frappe.msgprint(__('No Lab Tests created'));
+						}
 						listview.refresh();
 					}
 				},
 				freeze: true,
-				freeze_message: "Creating Lab Test..."
+				freeze_message: 'Creating Lab Tests...'
 			});
 			dialog.hide();
 		}
diff --git a/erpnext/healthcare/doctype/lab_test_groups/__init__.py b/erpnext/healthcare/doctype/lab_test_group_template/__init__.py
similarity index 100%
rename from erpnext/healthcare/doctype/lab_test_groups/__init__.py
rename to erpnext/healthcare/doctype/lab_test_group_template/__init__.py
diff --git a/erpnext/healthcare/doctype/lab_test_group_template/lab_test_group_template.json b/erpnext/healthcare/doctype/lab_test_group_template/lab_test_group_template.json
new file mode 100644
index 0000000..beea7a3
--- /dev/null
+++ b/erpnext/healthcare/doctype/lab_test_group_template/lab_test_group_template.json
@@ -0,0 +1,118 @@
+{
+ "actions": [],
+ "allow_copy": 1,
+ "beta": 1,
+ "creation": "2016-03-29 17:37:29.913583",
+ "doctype": "DocType",
+ "document_type": "Setup",
+ "engine": "InnoDB",
+ "field_order": [
+  "template_or_new_line",
+  "lab_test_template",
+  "lab_test_rate",
+  "lab_test_description",
+  "group_event",
+  "group_test_uom",
+  "secondary_uom",
+  "conversion_factor",
+  "allow_blank",
+  "column_break_8",
+  "group_test_normal_range"
+ ],
+ "fields": [
+  {
+   "default": "Add Test",
+   "fieldname": "template_or_new_line",
+   "fieldtype": "Select",
+   "options": "Add Test\nAdd New Line",
+   "print_hide": 1,
+   "report_hide": 1
+  },
+  {
+   "depends_on": "eval:doc.template_or_new_line == 'Add Test'",
+   "fieldname": "lab_test_template",
+   "fieldtype": "Link",
+   "ignore_user_permissions": 1,
+   "in_list_view": 1,
+   "label": "Test Name",
+   "options": "Lab Test Template"
+  },
+  {
+   "fetch_from": "lab_test_template.lab_test_rate",
+   "fieldname": "lab_test_rate",
+   "fieldtype": "Currency",
+   "label": "Rate",
+   "print_hide": 1,
+   "read_only": 1,
+   "report_hide": 1
+  },
+  {
+   "fetch_from": "lab_test_template.lab_test_description",
+   "fieldname": "lab_test_description",
+   "fieldtype": "Data",
+   "ignore_xss_filter": 1,
+   "in_list_view": 1,
+   "label": "Description",
+   "read_only": 1
+  },
+  {
+   "depends_on": "eval:doc.template_or_new_line == 'Add New Line'",
+   "fieldname": "group_event",
+   "fieldtype": "Data",
+   "ignore_xss_filter": 1,
+   "in_list_view": 1,
+   "label": "Event"
+  },
+  {
+   "depends_on": "eval:doc.template_or_new_line =='Add New Line'",
+   "fieldname": "group_test_uom",
+   "fieldtype": "Link",
+   "ignore_user_permissions": 1,
+   "label": "UOM",
+   "options": "Lab Test UOM"
+  },
+  {
+   "depends_on": "eval:doc.template_or_new_line == 'Add New Line'",
+   "fieldname": "group_test_normal_range",
+   "fieldtype": "Long Text",
+   "ignore_xss_filter": 1,
+   "label": "Normal Range"
+  },
+  {
+   "fieldname": "column_break_8",
+   "fieldtype": "Column Break"
+  },
+  {
+   "depends_on": "eval:doc.template_or_new_line =='Add New Line'",
+   "fieldname": "secondary_uom",
+   "fieldtype": "Link",
+   "label": "Secondary UOM",
+   "options": "Lab Test UOM"
+  },
+  {
+   "depends_on": "secondary_uom",
+   "fieldname": "conversion_factor",
+   "fieldtype": "Float",
+   "label": "Conversion Factor"
+  },
+  {
+   "default": "0",
+   "depends_on": "eval:doc.template_or_new_line == 'Add New Line'",
+   "fieldname": "allow_blank",
+   "fieldtype": "Check",
+   "in_list_view": 1,
+   "label": "Allow Blank"
+  }
+ ],
+ "istable": 1,
+ "links": [],
+ "modified": "2020-06-24 10:59:01.921924",
+ "modified_by": "Administrator",
+ "module": "Healthcare",
+ "name": "Lab Test Group Template",
+ "owner": "Administrator",
+ "permissions": [],
+ "restrict_to_domain": "Healthcare",
+ "sort_field": "modified",
+ "sort_order": "DESC"
+}
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/special_test_template/special_test_template.py b/erpnext/healthcare/doctype/lab_test_group_template/lab_test_group_template.py
similarity index 84%
rename from erpnext/healthcare/doctype/special_test_template/special_test_template.py
rename to erpnext/healthcare/doctype/lab_test_group_template/lab_test_group_template.py
index e4e0d5b..1e2cef4 100644
--- a/erpnext/healthcare/doctype/special_test_template/special_test_template.py
+++ b/erpnext/healthcare/doctype/lab_test_group_template/lab_test_group_template.py
@@ -5,5 +5,5 @@
 from __future__ import unicode_literals
 from frappe.model.document import Document
 
-class SpecialTestTemplate(Document):
+class LabTestGroupTemplate(Document):
 	pass
diff --git a/erpnext/healthcare/doctype/lab_test_groups/lab_test_groups.json b/erpnext/healthcare/doctype/lab_test_groups/lab_test_groups.json
deleted file mode 100644
index e51d8b7..0000000
--- a/erpnext/healthcare/doctype/lab_test_groups/lab_test_groups.json
+++ /dev/null
@@ -1,310 +0,0 @@
-{
- "allow_copy": 1, 
- "allow_guest_to_view": 0, 
- "allow_import": 0, 
- "allow_rename": 0, 
- "beta": 1, 
- "creation": "2016-03-29 17:37:29.913583", 
- "custom": 0, 
- "docstatus": 0, 
- "doctype": "DocType", 
- "document_type": "Setup", 
- "editable_grid": 0, 
- "fields": [
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "default": "Add Test", 
-   "depends_on": "", 
-   "fieldname": "template_or_new_line", 
-   "fieldtype": "Select", 
-   "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": "", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Add Test\nAdd new line", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 1, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 1, 
-   "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, 
-   "depends_on": "eval:doc.template_or_new_line == 'Add Test'", 
-   "fieldname": "lab_test_template", 
-   "fieldtype": "Link", 
-   "hidden": 0, 
-   "ignore_user_permissions": 1, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Test Name", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Lab Test Template", 
-   "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_from": "lab_test_template.lab_test_rate", 
-   "fieldname": "lab_test_rate", 
-   "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": "Rate", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 1, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 1, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 1, 
-   "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_from": "lab_test_template.lab_test_description", 
-   "fieldname": "lab_test_description", 
-   "fieldtype": "Data", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 1, 
-   "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": 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, 
-   "depends_on": "eval:doc.template_or_new_line == 'Add new line'", 
-   "fieldname": "group_event", 
-   "fieldtype": "Data", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 1, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Event", 
-   "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, 
-   "depends_on": "eval:doc.template_or_new_line =='Add new line'", 
-   "fieldname": "group_test_uom", 
-   "fieldtype": "Link", 
-   "hidden": 0, 
-   "ignore_user_permissions": 1, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "UOM", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Lab Test UOM", 
-   "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, 
-   "depends_on": "eval:doc.template_or_new_line == 'Add new line'", 
-   "fieldname": "group_test_normal_range", 
-   "fieldtype": "Long Text", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 1, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Normal Range", 
-   "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, 
-   "fieldname": "column_break_8", 
-   "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
-  }
- ], 
- "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-04 09:49:24.817787", 
- "modified_by": "Administrator", 
- "module": "Healthcare", 
- "name": "Lab Test Groups", 
- "name_case": "", 
- "owner": "Administrator", 
- "permissions": [], 
- "quick_entry": 0, 
- "read_only": 0, 
- "read_only_onload": 0, 
- "restrict_to_domain": "Healthcare", 
- "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/healthcare/doctype/lab_test_template/lab_test_template.js b/erpnext/healthcare/doctype/lab_test_template/lab_test_template.js
index 5c9bf49..2e41f51 100644
--- a/erpnext/healthcare/doctype/lab_test_template/lab_test_template.js
+++ b/erpnext/healthcare/doctype/lab_test_template/lab_test_template.js
@@ -1,19 +1,28 @@
 // Copyright (c) 2016, ESS
 // License: ESS license.txt
 
-frappe.ui.form.on("Lab Test Template",{
+frappe.ui.form.on('Lab Test Template', {
 	lab_test_name: function(frm) {
 		if (!frm.doc.lab_test_code)
-			frm.set_value("lab_test_code", frm.doc.lab_test_name);
+			frm.set_value('lab_test_code', frm.doc.lab_test_name);
 		if (!frm.doc.lab_test_description)
-			frm.set_value("lab_test_description", frm.doc.lab_test_name);
+			frm.set_value('lab_test_description', frm.doc.lab_test_name);
 	},
 	refresh : function(frm) {
-		// Restrict Special, Grouped type templates in Child TestGroups
-		frm.set_query("lab_test_template", "lab_test_groups", function() {
+		// Restrict Special, Grouped type templates in Child Test Groups
+		frm.set_query('lab_test_template', 'lab_test_groups', function() {
 			return {
 				filters: {
-					lab_test_template_type: ['in',['Single','Compound']]
+					lab_test_template_type: ['in', ['Single','Compound']]
+				}
+			};
+		});
+	},
+	medical_code: function(frm) {
+		frm.set_query('medical_code', function() {
+			return {
+				filters: {
+					medical_code_standard: frm.doc.medical_code_standard
 				}
 			};
 		});
@@ -21,10 +30,10 @@
 });
 
 cur_frm.cscript.custom_refresh = function(doc) {
-	cur_frm.set_df_property("lab_test_code", "read_only", doc.__islocal ? 0 : 1);
+	cur_frm.set_df_property('lab_test_code', 'read_only', doc.__islocal ? 0 : 1);
 
 	if (!doc.__islocal) {
-		cur_frm.add_custom_button(__("Change Template Code"), function() {
+		cur_frm.add_custom_button(__('Change Template Code'), function() {
 			change_template_code(doc);
 		});
 	}
@@ -32,12 +41,12 @@
 
 let change_template_code = function(doc) {
 	let d = new frappe.ui.Dialog({
-		title:__("Change Template Code"),
+		title:__('Change Template Code'),
 		fields:[
 			{
-				"fieldtype": "Data",
-				"label": "Lab Test Template Code",
-				"fieldname": "lab_test_code",
+				'fieldtype': 'Data',
+				'label': 'Lab Test Template Code',
+				'fieldname': 'lab_test_code',
 				reqd: 1
 			}
 		],
@@ -45,49 +54,44 @@
 			let values = d.get_values();
 			if (values) {
 				frappe.call({
-					"method": "erpnext.healthcare.doctype.lab_test_template.lab_test_template.change_test_code_from_template",
-					"args": {lab_test_code: values.lab_test_code, doc: doc},
+					'method': 'erpnext.healthcare.doctype.lab_test_template.lab_test_template.change_test_code_from_template',
+					'args': {lab_test_code: values.lab_test_code, doc: doc},
 					callback: function (data) {
-						frappe.set_route("Form", "Lab Test Template", data.message);
+						frappe.set_route('Form', 'Lab Test Template', data.message);
 					}
 				});
 			}
 			d.hide();
 		},
-		primary_action_label: __("Change Template Code")
+		primary_action_label: __('Change Template Code')
 	});
 	d.show();
 
 	d.set_values({
-		"lab_test_code": doc.lab_test_code
+		'lab_test_code': doc.lab_test_code
 	});
 };
 
-frappe.ui.form.on("Lab Test Template", "lab_test_name", function(frm){
-
+frappe.ui.form.on('Lab Test Template', 'lab_test_name', function(frm) {
 	frm.doc.change_in_item = 1;
-
-});
-frappe.ui.form.on("Lab Test Template", "lab_test_rate", function(frm){
-
-	frm.doc.change_in_item = 1;
-
-});
-frappe.ui.form.on("Lab Test Template", "lab_test_group", function(frm){
-
-	frm.doc.change_in_item = 1;
-
-});
-frappe.ui.form.on("Lab Test Template", "lab_test_description", function(frm){
-
-	frm.doc.change_in_item = 1;
-
 });
 
-frappe.ui.form.on("Lab Test Groups", "template_or_new_line", function (frm, cdt, cdn) {
+frappe.ui.form.on('Lab Test Template', 'lab_test_rate', function(frm) {
+	frm.doc.change_in_item = 1;
+});
+
+frappe.ui.form.on('Lab Test Template', 'lab_test_group', function(frm) {
+	frm.doc.change_in_item = 1;
+});
+
+frappe.ui.form.on('Lab Test Template', 'lab_test_description', function(frm) {
+	frm.doc.change_in_item = 1;
+});
+
+frappe.ui.form.on('Lab Test Groups', 'template_or_new_line', function (frm, cdt, cdn) {
 	let child = locals[cdt][cdn];
-	if (child.template_or_new_line == "Add new line") {
-		frappe.model.set_value(cdt, cdn, 'lab_test_template', "");
-		frappe.model.set_value(cdt, cdn, 'lab_test_description', "");
+	if (child.template_or_new_line == 'Add New Line') {
+		frappe.model.set_value(cdt, cdn, 'lab_test_template', '');
+		frappe.model.set_value(cdt, cdn, 'lab_test_description', '');
 	}
 });
diff --git a/erpnext/healthcare/doctype/lab_test_template/lab_test_template.json b/erpnext/healthcare/doctype/lab_test_template/lab_test_template.json
index a606bc4..db64297 100644
--- a/erpnext/healthcare/doctype/lab_test_template/lab_test_template.json
+++ b/erpnext/healthcare/doctype/lab_test_template/lab_test_template.json
@@ -15,28 +15,38 @@
   "lab_test_group",
   "department",
   "column_break_3",
-  "lab_test_template_type",
   "disabled",
+  "lab_test_template_type",
   "is_billable",
   "lab_test_rate",
+  "section_break_description",
+  "lab_test_description",
   "section_break_normal",
   "lab_test_uom",
-  "lab_test_normal_range",
+  "secondary_uom",
+  "conversion_factor",
   "column_break_10",
+  "lab_test_normal_range",
   "section_break_compound",
   "normal_test_templates",
   "section_break_special",
   "sensitivity",
-  "special_test_template",
+  "descriptive_test_templates",
   "section_break_group",
   "lab_test_groups",
-  "section_break_description",
-  "lab_test_description",
+  "medical_coding_section",
+  "medical_code_standard",
+  "medical_code",
   "sb_sample_collection",
   "sample",
   "sample_uom",
   "sample_qty",
   "sample_details",
+  "worksheet_section",
+  "worksheet_instructions",
+  "result_legend_section",
+  "legend_print_position",
+  "result_legend",
   "change_in_item"
  ],
  "fields": [
@@ -92,7 +102,7 @@
    "fieldtype": "Column Break"
   },
   {
-   "description": "Single for results which require only a single input, result UOM and normal value \n<br>\nCompound for results which require multiple input fields with corresponding event names, result UOMs and normal values\n<br>\nDescriptive for tests which have multiple result components and corresponding result entry fields. \n<br>\nGrouped for test templates which are a group of other test templates.\n<br>\nNo Result for tests with no results. Also, no Lab Test is created. e.g.. Sub Tests for Grouped results.",
+   "description": "<b>Single</b>: Results which require only a single input.\n<br>\n<b>Compound</b>: Results which require multiple event inputs.\n<br>\n<b>Descriptive</b>: Tests which have multiple result components with manual result entry.\n<br>\n<b>Grouped</b>: Test templates which are a group of other test templates.\n<br>\n<b>No Result</b>: Tests with no results, can be ordered and billed but no Lab Test will be created. e.g.. Sub Tests for Grouped results",
    "fieldname": "lab_test_template_type",
    "fieldtype": "Select",
    "in_standard_filter": 1,
@@ -118,6 +128,24 @@
    "mandatory_depends_on": "eval:doc.is_billable == 1"
   },
   {
+   "fieldname": "medical_coding_section",
+   "fieldtype": "Section Break",
+   "label": "Medical Coding"
+  },
+  {
+   "depends_on": "medical_code_standard",
+   "fieldname": "medical_code",
+   "fieldtype": "Link",
+   "label": "Medical Code",
+   "options": "Medical Code"
+  },
+  {
+   "fieldname": "medical_code_standard",
+   "fieldtype": "Link",
+   "label": "Medical Code Standard",
+   "options": "Medical Code Standard"
+  },
+  {
    "depends_on": "eval:doc.lab_test_template_type == 'Single'",
    "fieldname": "section_break_normal",
    "fieldtype": "Section Break",
@@ -156,7 +184,7 @@
    "depends_on": "eval:doc.lab_test_template_type == 'Descriptive'",
    "fieldname": "section_break_special",
    "fieldtype": "Section Break",
-   "label": "Special"
+   "label": "Descriptive"
   },
   {
    "default": "0",
@@ -165,11 +193,6 @@
    "label": "Sensitivity"
   },
   {
-   "fieldname": "special_test_template",
-   "fieldtype": "Table",
-   "options": "Special Test Template"
-  },
-  {
    "depends_on": "eval:doc.lab_test_template_type == 'Grouped'",
    "fieldname": "section_break_group",
    "fieldtype": "Section Break",
@@ -178,20 +201,23 @@
   {
    "fieldname": "lab_test_groups",
    "fieldtype": "Table",
-   "options": "Lab Test Groups"
+   "options": "Lab Test Group Template"
   },
   {
+   "collapsible": 1,
    "fieldname": "section_break_description",
-   "fieldtype": "Section Break"
+   "fieldtype": "Section Break",
+   "label": "Description "
   },
   {
    "fieldname": "lab_test_description",
-   "fieldtype": "Text",
+   "fieldtype": "Text Editor",
    "ignore_xss_filter": 1,
    "label": "Description",
    "no_copy": 1
   },
   {
+   "collapsible": 1,
    "fieldname": "sb_sample_collection",
    "fieldtype": "Section Break",
    "label": "Sample Collection"
@@ -234,13 +260,61 @@
   },
   {
    "fieldname": "sample_details",
-   "fieldtype": "Text",
+   "fieldtype": "Small Text",
    "ignore_xss_filter": 1,
    "label": "Collection Details"
+  },
+  {
+   "collapsible": 1,
+   "description": "Information to help easily interpret the test report, will be printed as part of the Lab Test result.",
+   "fieldname": "result_legend_section",
+   "fieldtype": "Section Break",
+   "label": "Result Legend Print"
+  },
+  {
+   "fieldname": "result_legend",
+   "fieldtype": "Text Editor",
+   "label": "Result Legend"
+  },
+  {
+   "fieldname": "legend_print_position",
+   "fieldtype": "Select",
+   "label": "Print Position",
+   "options": "Bottom\nTop\nBoth"
+  },
+  {
+   "fieldname": "secondary_uom",
+   "fieldtype": "Link",
+   "label": "Secondary UOM",
+   "options": "Lab Test UOM"
+  },
+  {
+   "depends_on": "secondary_uom",
+   "fieldname": "conversion_factor",
+   "fieldtype": "Float",
+   "label": "Conversion Factor",
+   "mandatory_depends_on": "secondary_uom"
+  },
+  {
+   "description": "Instructions to be printed on the worksheet",
+   "fieldname": "worksheet_instructions",
+   "fieldtype": "Text Editor",
+   "label": "Worksheet Instructions"
+  },
+  {
+   "collapsible": 1,
+   "fieldname": "worksheet_section",
+   "fieldtype": "Section Break",
+   "label": "Worksheet Print"
+  },
+  {
+   "fieldname": "descriptive_test_templates",
+   "fieldtype": "Table",
+   "options": "Descriptive Test Template"
   }
  ],
  "links": [],
- "modified": "2020-03-25 16:53:01.740103",
+ "modified": "2020-07-13 12:57:09.925436",
  "modified_by": "Administrator",
  "module": "Healthcare",
  "name": "Lab Test Template",
diff --git a/erpnext/healthcare/doctype/lab_test_template/lab_test_template.py b/erpnext/healthcare/doctype/lab_test_template/lab_test_template.py
index 3521561..6f0d08c 100644
--- a/erpnext/healthcare/doctype/lab_test_template/lab_test_template.py
+++ b/erpnext/healthcare/doctype/lab_test_template/lab_test_template.py
@@ -14,37 +14,37 @@
 			create_item_from_template(self)
 
 	def validate(self):
+		if self.is_billable and (not self.lab_test_rate or self.lab_test_rate <= 0.0):
+			frappe.throw(_("Standard Selling Rate should be greater than zero."))
+		self.validate_conversion_factor()
 		self.enable_disable_item()
 
 	def on_update(self):
-		# if change_in_item update Item and Price List
+		# If change_in_item update Item and Price List
 		if self.change_in_item and self.is_billable and self.item:
 			self.update_item()
 			item_price = self.item_price_exists()
 			if not item_price:
-				if self.lab_test_rate != 0.0:
-					price_list_name = frappe.db.get_value("Price List", {"selling": 1})
-					if self.lab_test_rate:
-						make_item_price(self.lab_test_code, price_list_name, self.lab_test_rate)
-					else:
-						make_item_price(self.lab_test_code, price_list_name, 0.0)
+				if self.lab_test_rate and self.lab_test_rate > 0.0:
+					price_list_name = frappe.db.get_value('Price List', {'selling': 1})
+					make_item_price(self.lab_test_code, price_list_name, self.lab_test_rate)
 			else:
-				frappe.db.set_value("Item Price", item_price, "price_list_rate", self.lab_test_rate)
+				frappe.db.set_value('Item Price', item_price, 'price_list_rate', self.lab_test_rate)
 
-			frappe.db.set_value(self.doctype, self.name, "change_in_item", 0)
+			self.db_set('change_in_item', 0)
 
 		elif not self.is_billable and self.item:
-			frappe.db.set_value("Item", self.item, "disabled", 1)
+			frappe.db.set_value('Item', self.item, 'disabled', 1)
 
 		self.reload()
 
 	def on_trash(self):
-		# remove template reference from item and disable item
+		# Remove template reference from item and disable item
 		if self.item:
 			try:
-				frappe.delete_doc("Item", self.item)
+				frappe.delete_doc('Item', self.item)
 			except Exception:
-				frappe.throw(_("Not permitted. Please disable the Lab Test Template"))
+				frappe.throw(_('Not permitted. Please disable the Lab Test Template'))
 
 	def enable_disable_item(self):
 		if self.is_billable:
@@ -54,78 +54,86 @@
 				frappe.db.set_value('Item', self.item, 'disabled', 0)
 
 	def update_item(self):
-		item = frappe.get_doc("Item", self.item)
+		item = frappe.get_doc('Item', self.item)
 		if item:
 			item.update({
-				"item_name": self.lab_test_name,
-				"item_group": self.lab_test_group,
-				"disabled": 0,
-				"standard_rate": self.lab_test_rate,
-				"description": self.lab_test_description
+				'item_name': self.lab_test_name,
+				'item_group': self.lab_test_group,
+				'disabled': 0,
+				'standard_rate': self.lab_test_rate,
+				'description': self.lab_test_description
 			})
 			item.save()
 
 	def item_price_exists(self):
-		item_price = frappe.db.exists({"doctype": "Item Price", "item_code": self.lab_test_code})
+		item_price = frappe.db.exists({'doctype': 'Item Price', 'item_code': self.lab_test_code})
 		if item_price:
 			return item_price[0][0]
 		else:
 			return False
 
+	def validate_conversion_factor(self):
+		if self.lab_test_template_type == "Single" and self.secondary_uom and not self.conversion_factor:
+			frappe.throw(_("Conversion Factor is mandatory"))
+		if self.lab_test_template_type == "Compound":
+			for item in self.normal_test_templates:
+				if item.secondary_uom and not item.conversion_factor:
+					frappe.throw(_("Conversion Factor is mandatory"))
+		if self.lab_test_template_type == "Grouped":
+			for group in self.lab_test_groups:
+				if group.template_or_new_line == "Add New Line" and group.secondary_uom and not group.conversion_factor:
+					frappe.throw(_("Conversion Factor is mandatory"))
+
 
 def create_item_from_template(doc):
-	disabled = doc.disabled
-	if doc.is_billable and not doc.disabled:
-		disabled = 0
-
 	uom = frappe.db.exists('UOM', 'Unit') or frappe.db.get_single_value('Stock Settings', 'stock_uom')
-	# insert item
+	# Insert item
 	item =  frappe.get_doc({
-		"doctype": "Item",
-		"item_code": doc.lab_test_code,
-		"item_name":doc.lab_test_name,
-		"item_group": doc.lab_test_group,
-		"description":doc.lab_test_description,
-		"is_sales_item": 1,
-		"is_service_item": 1,
-		"is_purchase_item": 0,
-		"is_stock_item": 0,
-		"show_in_website": 0,
-		"is_pro_applicable": 0,
-		"disabled": disabled,
-		"stock_uom": uom
-	}).insert(ignore_permissions=True, ignore_mandatory=True)
+		'doctype': 'Item',
+		'item_code': doc.lab_test_code,
+		'item_name':doc.lab_test_name,
+		'item_group': doc.lab_test_group,
+		'description':doc.lab_test_description,
+		'is_sales_item': 1,
+		'is_service_item': 1,
+		'is_purchase_item': 0,
+		'is_stock_item': 0,
+		'include_item_in_manufacturing': 0,
+		'show_in_website': 0,
+		'is_pro_applicable': 0,
+		'disabled': 0 if doc.is_billable and not doc.disabled else doc.disabled, 
+		'stock_uom': uom
+	}).insert(ignore_permissions = True, ignore_mandatory = True)
 
-	# insert item price
-	# get item price list to insert item price
-	if doc.lab_test_rate != 0.0:
-		price_list_name = frappe.db.get_value("Price List", {"selling": 1})
+	# Insert item price
+	if doc.is_billable and doc.lab_test_rate != 0.0:
+		price_list_name = frappe.db.get_value('Price List', {'selling': 1})
 		if doc.lab_test_rate:
 			make_item_price(item.name, price_list_name, doc.lab_test_rate)
 		else:
 			make_item_price(item.name, price_list_name, 0.0)
 	# Set item in the template
-	frappe.db.set_value("Lab Test Template", doc.name, "item", item.name)
+	frappe.db.set_value('Lab Test Template', doc.name, 'item', item.name)
 
 	doc.reload()
 
 def make_item_price(item, price_list_name, item_price):
 	frappe.get_doc({
-		"doctype": "Item Price",
-		"price_list": price_list_name,
-		"item_code": item,
-		"price_list_rate": item_price
-	}).insert(ignore_permissions=True, ignore_mandatory=True)
+		'doctype': 'Item Price',
+		'price_list': price_list_name,
+		'item_code': item,
+		'price_list_rate': item_price
+	}).insert(ignore_permissions = True, ignore_mandatory = True)
 
 @frappe.whitelist()
 def change_test_code_from_template(lab_test_code, doc):
 	doc = frappe._dict(json.loads(doc))
 
-	if frappe.db.exists({ "doctype": "Item", "item_code": lab_test_code}):
-		frappe.throw(_("Lab Test Item {0} already exist").format(lab_test_code))
+	if frappe.db.exists({'doctype': 'Item', 'item_code': lab_test_code}):
+		frappe.throw(_('Lab Test Item {0} already exist').format(lab_test_code))
 	else:
-		rename_doc("Item", doc.name, lab_test_code, ignore_permissions=True)
-		frappe.db.set_value("Lab Test Template", doc.name, "lab_test_code", lab_test_code)
-		frappe.db.set_value("Lab Test Template", doc.name, "lab_test_name", lab_test_code)
-		rename_doc("Lab Test Template", doc.name, lab_test_code, ignore_permissions=True)
-	return lab_test_code
\ No newline at end of file
+		rename_doc('Item', doc.name, lab_test_code, ignore_permissions = True)
+		frappe.db.set_value('Lab Test Template', doc.name, 'lab_test_code', lab_test_code)
+		frappe.db.set_value('Lab Test Template', doc.name, 'lab_test_name', lab_test_code)
+		rename_doc('Lab Test Template', doc.name, lab_test_code, ignore_permissions = True)
+	return lab_test_code
diff --git a/erpnext/healthcare/doctype/lab_test_template/lab_test_template_list.js b/erpnext/healthcare/doctype/lab_test_template/lab_test_template_list.js
index a86075f..a3417eb 100644
--- a/erpnext/healthcare/doctype/lab_test_template/lab_test_template_list.js
+++ b/erpnext/healthcare/doctype/lab_test_template/lab_test_template_list.js
@@ -2,6 +2,6 @@
 (c) ESS 2015-16
 */
 frappe.listview_settings['Lab Test Template'] = {
-	add_fields: ["lab_test_name", "lab_test_code", "lab_test_rate"],
-	filters: [["disabled", "=", 0]]
+	add_fields: ['lab_test_name', 'lab_test_code', 'lab_test_rate'],
+	filters: [['disabled', '=', 0]]
 };
diff --git a/erpnext/healthcare/doctype/medical_code/medical_code.json b/erpnext/healthcare/doctype/medical_code/medical_code.json
index a2e7247..5d69830 100644
--- a/erpnext/healthcare/doctype/medical_code/medical_code.json
+++ b/erpnext/healthcare/doctype/medical_code/medical_code.json
@@ -1,156 +1,69 @@
 {
- "allow_copy": 1, 
- "allow_guest_to_view": 0, 
- "allow_import": 1, 
- "allow_rename": 1, 
- "beta": 1, 
- "creation": "2017-06-21 13:02:56.122897", 
- "custom": 0, 
- "docstatus": 0, 
- "doctype": "DocType", 
- "document_type": "", 
- "editable_grid": 1, 
- "engine": "InnoDB", 
+ "actions": [],
+ "allow_copy": 1,
+ "allow_import": 1,
+ "allow_rename": 1,
+ "beta": 1,
+ "creation": "2017-06-21 13:02:56.122897",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "medical_code_standard",
+  "code",
+  "description"
+ ],
  "fields": [
   {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "medical_code_standard", 
-   "fieldtype": "Link", 
-   "hidden": 0, 
-   "ignore_user_permissions": 1, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Medical Code Standard", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Medical Code Standard", 
-   "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": "medical_code_standard",
+   "fieldtype": "Link",
+   "ignore_user_permissions": 1,
+   "label": "Medical Code Standard",
+   "options": "Medical Code Standard",
+   "reqd": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "code", 
-   "fieldtype": "Data", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 1, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Code", 
-   "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, 
-   "unique": 0
-  }, 
+   "fieldname": "code",
+   "fieldtype": "Data",
+   "ignore_xss_filter": 1,
+   "in_list_view": 1,
+   "label": "Code",
+   "reqd": 1,
+   "unique": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 1, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "description", 
-   "fieldtype": "Small Text", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 1, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Description", 
-   "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
+   "bold": 1,
+   "fieldname": "description",
+   "fieldtype": "Small Text",
+   "ignore_xss_filter": 1,
+   "in_list_view": 1,
+   "label": "Description"
   }
- ], 
- "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-10-04 17:08:11.053418", 
- "modified_by": "Administrator", 
- "module": "Healthcare", 
- "name": "Medical Code", 
- "name_case": "", 
- "owner": "Administrator", 
+ ],
+ "links": [],
+ "modified": "2020-06-29 14:02:30.980032",
+ "modified_by": "Administrator",
+ "module": "Healthcare",
+ "name": "Medical Code",
+ "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": "Physician", 
-   "set_user_permissions": 0, 
-   "share": 1, 
-   "submit": 0, 
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "export": 1,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "Physician",
+   "share": 1,
    "write": 1
   }
- ], 
- "quick_entry": 1, 
- "read_only": 0, 
- "read_only_onload": 0, 
- "restrict_to_domain": "Healthcare", 
- "search_fields": "code, description", 
- "show_name_in_global_search": 0, 
- "sort_field": "modified", 
- "sort_order": "DESC", 
- "title_field": "", 
- "track_changes": 1, 
- "track_seen": 0
+ ],
+ "quick_entry": 1,
+ "restrict_to_domain": "Healthcare",
+ "search_fields": "code, description",
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
 }
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/normal_test_items/normal_test_items.js b/erpnext/healthcare/doctype/normal_test_items/normal_test_items.js
deleted file mode 100644
index 0371ddd..0000000
--- a/erpnext/healthcare/doctype/normal_test_items/normal_test_items.js
+++ /dev/null
@@ -1,4 +0,0 @@
-// Copyright (c) 2016, ESS
-// License: ESS license.txt
-
-
diff --git a/erpnext/healthcare/doctype/normal_test_items/normal_test_items.json b/erpnext/healthcare/doctype/normal_test_items/normal_test_items.json
deleted file mode 100644
index a7a952b..0000000
--- a/erpnext/healthcare/doctype/normal_test_items/normal_test_items.json
+++ /dev/null
@@ -1,301 +0,0 @@
-{
- "allow_copy": 1, 
- "allow_guest_to_view": 0, 
- "allow_import": 0, 
- "allow_rename": 0, 
- "beta": 1, 
- "creation": "2016-02-22 15:06:08.295224", 
- "custom": 0, 
- "docstatus": 0, 
- "doctype": "DocType", 
- "document_type": "Document", 
- "editable_grid": 1, 
- "fields": [
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "lab_test_name", 
-   "fieldtype": "Data", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 1, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Test 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
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "lab_test_event", 
-   "fieldtype": "Data", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 1, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Event", 
-   "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, 
-   "depends_on": "eval:doc.require_result_value == 1 ", 
-   "fieldname": "result_value", 
-   "fieldtype": "Data", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 1, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Result Value", 
-   "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, 
-   "fieldname": "lab_test_uom", 
-   "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": "UOM", 
-   "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, 
-   "fieldname": "normal_range", 
-   "fieldtype": "Long Text", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 1, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Normal Range", 
-   "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, 
-   "fieldname": "lab_test_comment", 
-   "fieldtype": "Data", 
-   "hidden": 1, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Comment", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 1, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 1, 
-   "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, 
-   "default": "0", 
-   "fieldname": "require_result_value", 
-   "fieldtype": "Check", 
-   "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": "Require Result Value", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 1, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 1, 
-   "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, 
-   "fieldname": "template", 
-   "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": "Template", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Lab Test Template", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 1, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 1, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }
- ], 
- "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-04 11:42:43.095726", 
- "modified_by": "Administrator", 
- "module": "Healthcare", 
- "name": "Normal Test Items", 
- "name_case": "", 
- "owner": "Administrator", 
- "permissions": [], 
- "quick_entry": 0, 
- "read_only": 0, 
- "read_only_onload": 0, 
- "restrict_to_domain": "Healthcare", 
- "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/healthcare/doctype/normal_test_items/normal_test_items.py b/erpnext/healthcare/doctype/normal_test_items/normal_test_items.py
deleted file mode 100644
index a0069d7..0000000
--- a/erpnext/healthcare/doctype/normal_test_items/normal_test_items.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# -*- coding: utf-8 -*-
-# Copyright (c) 2015, ESS and contributors
-# For license information, please see license.txt
-
-from __future__ import unicode_literals
-from frappe.model.document import Document
-
-class NormalTestItems(Document):
-	pass
diff --git a/erpnext/healthcare/doctype/normal_test_items/__init__.py b/erpnext/healthcare/doctype/normal_test_result/__init__.py
similarity index 100%
rename from erpnext/healthcare/doctype/normal_test_items/__init__.py
rename to erpnext/healthcare/doctype/normal_test_result/__init__.py
diff --git a/erpnext/healthcare/doctype/normal_test_result/normal_test_result.json b/erpnext/healthcare/doctype/normal_test_result/normal_test_result.json
new file mode 100644
index 0000000..c8f43d3
--- /dev/null
+++ b/erpnext/healthcare/doctype/normal_test_result/normal_test_result.json
@@ -0,0 +1,186 @@
+{
+ "actions": [],
+ "allow_copy": 1,
+ "beta": 1,
+ "creation": "2016-02-22 15:06:08.295224",
+ "doctype": "DocType",
+ "document_type": "Document",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "lab_test_name",
+  "lab_test_event",
+  "result_value",
+  "lab_test_uom",
+  "secondary_uom_result",
+  "secondary_uom",
+  "conversion_factor",
+  "column_break_10",
+  "allow_blank",
+  "normal_range",
+  "lab_test_comment",
+  "bold",
+  "italic",
+  "underline",
+  "template",
+  "require_result_value"
+ ],
+ "fields": [
+  {
+   "fieldname": "lab_test_name",
+   "fieldtype": "Data",
+   "ignore_xss_filter": 1,
+   "in_list_view": 1,
+   "label": "Test Name",
+   "read_only": 1
+  },
+  {
+   "fieldname": "lab_test_event",
+   "fieldtype": "Data",
+   "ignore_xss_filter": 1,
+   "in_list_view": 1,
+   "label": "Event",
+   "read_only": 1
+  },
+  {
+   "depends_on": "eval:doc.require_result_value",
+   "fieldname": "result_value",
+   "fieldtype": "Data",
+   "ignore_xss_filter": 1,
+   "in_list_view": 1,
+   "label": "Result Value"
+  },
+  {
+   "depends_on": "eval:doc.require_result_value",
+   "fieldname": "lab_test_uom",
+   "fieldtype": "Link",
+   "label": "UOM",
+   "options": "Lab Test UOM",
+   "read_only": 1
+  },
+  {
+   "depends_on": "eval:doc.require_result_value",
+   "fieldname": "normal_range",
+   "fieldtype": "Long Text",
+   "ignore_xss_filter": 1,
+   "in_list_view": 1,
+   "label": "Normal Range",
+   "read_only": 1
+  },
+  {
+   "depends_on": "eval:doc.require_result_value",
+   "fieldname": "lab_test_comment",
+   "fieldtype": "Data",
+   "hidden": 1,
+   "in_list_view": 1,
+   "label": "Comment",
+   "no_copy": 1,
+   "print_hide": 1,
+   "report_hide": 1
+  },
+  {
+   "fieldname": "template",
+   "fieldtype": "Link",
+   "hidden": 1,
+   "label": "Template",
+   "options": "Lab Test Template",
+   "print_hide": 1,
+   "report_hide": 1
+  },
+  {
+   "depends_on": "eval:doc.require_result_value",
+   "fieldname": "secondary_uom",
+   "fieldtype": "Link",
+   "label": "Secondary UOM",
+   "options": "Lab Test UOM",
+   "print_hide": 1,
+   "read_only": 1
+  },
+  {
+   "depends_on": "secondary_uom",
+   "fieldname": "conversion_factor",
+   "fieldtype": "Float",
+   "label": "Conversion Factor",
+   "mandatory_depends_on": "secondary_uom",
+   "print_hide": 1,
+   "read_only": 1
+  },
+  {
+   "depends_on": "eval:doc.require_result_value && doc.result_value",
+   "fieldname": "secondary_uom_result",
+   "fieldtype": "Data",
+   "label": "Secondary UOM Result",
+   "no_copy": 1,
+   "print_hide": 1,
+   "read_only": 1
+  },
+  {
+   "allow_on_submit": 1,
+   "default": "0",
+   "depends_on": "eval:doc.require_result_value",
+   "fieldname": "bold",
+   "fieldtype": "Check",
+   "label": "Bold",
+   "no_copy": 1,
+   "print_hide": 1,
+   "report_hide": 1
+  },
+  {
+   "allow_on_submit": 1,
+   "default": "0",
+   "depends_on": "eval:doc.require_result_value",
+   "fieldname": "italic",
+   "fieldtype": "Check",
+   "label": "Italic",
+   "no_copy": 1,
+   "print_hide": 1,
+   "report_hide": 1
+  },
+  {
+   "allow_on_submit": 1,
+   "default": "0",
+   "depends_on": "eval:doc.require_result_value",
+   "fieldname": "underline",
+   "fieldtype": "Check",
+   "label": "Underline",
+   "no_copy": 1,
+   "print_hide": 1,
+   "report_hide": 1
+  },
+  {
+   "fieldname": "column_break_10",
+   "fieldtype": "Column Break"
+  },
+  {
+   "default": "0",
+   "fieldname": "require_result_value",
+   "fieldtype": "Check",
+   "hidden": 1,
+   "label": "Require Result Value",
+   "print_hide": 1,
+   "read_only": 1,
+   "report_hide": 1
+  },
+  {
+   "default": "1",
+   "depends_on": "eval:doc.require_result_value",
+   "fieldname": "allow_blank",
+   "fieldtype": "Check",
+   "label": "Allow Blank",
+   "print_hide": 1,
+   "read_only": 1,
+   "report_hide": 1
+  }
+ ],
+ "istable": 1,
+ "links": [],
+ "modified": "2020-07-08 16:03:17.522893",
+ "modified_by": "Administrator",
+ "module": "Healthcare",
+ "name": "Normal Test Result",
+ "owner": "Administrator",
+ "permissions": [],
+ "restrict_to_domain": "Healthcare",
+ "sort_field": "modified",
+ "sort_order": "DESC"
+}
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/lab_test_groups/lab_test_groups.py b/erpnext/healthcare/doctype/normal_test_result/normal_test_result.py
similarity index 85%
rename from erpnext/healthcare/doctype/lab_test_groups/lab_test_groups.py
rename to erpnext/healthcare/doctype/normal_test_result/normal_test_result.py
index c67531c..63abf02 100644
--- a/erpnext/healthcare/doctype/lab_test_groups/lab_test_groups.py
+++ b/erpnext/healthcare/doctype/normal_test_result/normal_test_result.py
@@ -5,5 +5,5 @@
 from __future__ import unicode_literals
 from frappe.model.document import Document
 
-class LabTestGroups(Document):
+class NormalTestResult(Document):
 	pass
diff --git a/erpnext/healthcare/doctype/normal_test_template/normal_test_template.json b/erpnext/healthcare/doctype/normal_test_template/normal_test_template.json
index a36c28d..8dd6476 100644
--- a/erpnext/healthcare/doctype/normal_test_template/normal_test_template.json
+++ b/erpnext/healthcare/doctype/normal_test_template/normal_test_template.json
@@ -1,202 +1,84 @@
 {
- "allow_copy": 1, 
- "allow_guest_to_view": 0, 
- "allow_import": 0, 
- "allow_rename": 0, 
- "beta": 1, 
- "creation": "2016-02-22 16:09:54.310628", 
- "custom": 0, 
- "docstatus": 0, 
- "doctype": "DocType", 
- "document_type": "Setup", 
- "editable_grid": 1, 
+ "actions": [],
+ "allow_copy": 1,
+ "beta": 1,
+ "creation": "2016-02-22 16:09:54.310628",
+ "doctype": "DocType",
+ "document_type": "Setup",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "heading_text",
+  "lab_test_event",
+  "allow_blank",
+  "lab_test_uom",
+  "secondary_uom",
+  "conversion_factor",
+  "column_break_5",
+  "normal_range"
+ ],
  "fields": [
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "heading_text", 
-   "fieldtype": "Heading", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 1, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Test", 
-   "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": "heading_text",
+   "fieldtype": "Heading",
+   "ignore_xss_filter": 1,
+   "label": "Test"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "lab_test_event", 
-   "fieldtype": "Data", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 1, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Event", 
-   "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": "lab_test_event",
+   "fieldtype": "Data",
+   "ignore_xss_filter": 1,
+   "in_list_view": 1,
+   "label": "Event"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "lab_test_uom", 
-   "fieldtype": "Link", 
-   "hidden": 0, 
-   "ignore_user_permissions": 1, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "UOM", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Lab Test UOM", 
-   "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": "lab_test_uom",
+   "fieldtype": "Link",
+   "ignore_user_permissions": 1,
+   "in_list_view": 1,
+   "label": "UOM",
+   "options": "Lab Test UOM"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "normal_range", 
-   "fieldtype": "Long Text", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 1, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Normal Range", 
-   "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": "normal_range",
+   "fieldtype": "Long Text",
+   "ignore_xss_filter": 1,
+   "in_list_view": 1,
+   "label": "Normal Range"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 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, 
-   "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_5",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "secondary_uom",
+   "fieldtype": "Link",
+   "label": "Secondary UOM",
+   "options": "Lab Test UOM"
+  },
+  {
+   "depends_on": "secondary_uom",
+   "fieldname": "conversion_factor",
+   "fieldtype": "Float",
+   "label": "Conversion Factor",
+   "mandatory_depends_on": "secondary_uom"
+  },
+  {
+   "default": "0",
+   "fieldname": "allow_blank",
+   "fieldtype": "Check",
+   "label": "Allow Blank"
   }
- ], 
- "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-04 11:42:30.766950", 
- "modified_by": "Administrator", 
- "module": "Healthcare", 
- "name": "Normal Test Template", 
- "name_case": "", 
- "owner": "Administrator", 
- "permissions": [], 
- "quick_entry": 0, 
- "read_only": 0, 
- "read_only_onload": 0, 
- "restrict_to_domain": "Healthcare", 
- "show_name_in_global_search": 0, 
- "sort_field": "modified", 
- "sort_order": "DESC", 
- "track_changes": 0, 
- "track_seen": 0, 
- "track_views": 0
+ ],
+ "istable": 1,
+ "links": [],
+ "modified": "2020-06-23 13:28:40.156224",
+ "modified_by": "Administrator",
+ "module": "Healthcare",
+ "name": "Normal Test Template",
+ "owner": "Administrator",
+ "permissions": [],
+ "restrict_to_domain": "Healthcare",
+ "sort_field": "modified",
+ "sort_order": "DESC"
 }
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/lab_test_groups/__init__.py b/erpnext/healthcare/doctype/organism/__init__.py
similarity index 100%
copy from erpnext/healthcare/doctype/lab_test_groups/__init__.py
copy to erpnext/healthcare/doctype/organism/__init__.py
diff --git a/erpnext/healthcare/doctype/organism/organism.js b/erpnext/healthcare/doctype/organism/organism.js
new file mode 100644
index 0000000..fbcb094
--- /dev/null
+++ b/erpnext/healthcare/doctype/organism/organism.js
@@ -0,0 +1,5 @@
+// Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+frappe.ui.form.on('Organism', {
+});
diff --git a/erpnext/healthcare/doctype/organism/organism.json b/erpnext/healthcare/doctype/organism/organism.json
new file mode 100644
index 0000000..88a7686
--- /dev/null
+++ b/erpnext/healthcare/doctype/organism/organism.json
@@ -0,0 +1,152 @@
+{
+ "allow_copy": 0,
+ "allow_events_in_timeline": 0,
+ "allow_guest_to_view": 0,
+ "allow_import": 0,
+ "allow_rename": 0,
+ "autoname": "field:organism",
+ "beta": 1,
+ "creation": "2019-09-06 16:29:07.797960",
+ "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,
+   "fetch_if_empty": 0,
+   "fieldname": "organism",
+   "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": "Organism",
+   "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": 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": "abbr",
+   "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": "Abbr",
+   "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": "2019-10-04 19:45:33.353753",
+ "modified_by": "Administrator",
+ "module": "Healthcare",
+ "name": "Organism",
+ "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": "Healthcare Administrator",
+   "set_user_permissions": 0,
+   "share": 1,
+   "submit": 0,
+   "write": 1
+  }
+ ],
+ "quick_entry": 1,
+ "read_only": 0,
+ "read_only_onload": 0,
+ "restrict_to_domain": "Healthcare",
+ "search_fields": "organism, abbr",
+ "show_name_in_global_search": 0,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "title_field": "organism",
+ "track_changes": 0,
+ "track_seen": 0,
+ "track_views": 0
+}
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/sensitivity_test_items/sensitivity_test_items.py b/erpnext/healthcare/doctype/organism/organism.py
similarity index 63%
copy from erpnext/healthcare/doctype/sensitivity_test_items/sensitivity_test_items.py
copy to erpnext/healthcare/doctype/organism/organism.py
index 35c8efd..1ead762 100644
--- a/erpnext/healthcare/doctype/sensitivity_test_items/sensitivity_test_items.py
+++ b/erpnext/healthcare/doctype/organism/organism.py
@@ -1,9 +1,9 @@
 # -*- coding: utf-8 -*-
-# Copyright (c) 2015, ESS and contributors
+# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
 # For license information, please see license.txt
 
 from __future__ import unicode_literals
 from frappe.model.document import Document
 
-class SensitivityTestItems(Document):
+class Organism(Document):
 	pass
diff --git a/erpnext/selling/doctype/pos_closing_voucher/test_pos_closing_voucher.js b/erpnext/healthcare/doctype/organism/test_organism.js
similarity index 68%
rename from erpnext/selling/doctype/pos_closing_voucher/test_pos_closing_voucher.js
rename to erpnext/healthcare/doctype/organism/test_organism.js
index 7633815..d57e553 100644
--- a/erpnext/selling/doctype/pos_closing_voucher/test_pos_closing_voucher.js
+++ b/erpnext/healthcare/doctype/organism/test_organism.js
@@ -2,15 +2,15 @@
 // rename this file from _test_[name] to test_[name] to activate
 // and remove above this line
 
-QUnit.test("test: POS Closing Voucher", function (assert) {
+QUnit.test("test: Organism", function (assert) {
 	let done = assert.async();
 
 	// number of asserts
 	assert.expect(1);
 
 	frappe.run_serially([
-		// insert a new POS Closing Voucher
-		() => frappe.tests.make('POS Closing Voucher', [
+		// insert a new Organism
+		() => frappe.tests.make('Organism', [
 			// values to be set
 			{key: 'value'}
 		]),
diff --git a/erpnext/healthcare/doctype/organism/test_organism.py b/erpnext/healthcare/doctype/organism/test_organism.py
new file mode 100644
index 0000000..ecb9665
--- /dev/null
+++ b/erpnext/healthcare/doctype/organism/test_organism.py
@@ -0,0 +1,8 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and Contributors
+# See license.txt
+from __future__ import unicode_literals
+import unittest
+
+class TestOrganism(unittest.TestCase):
+	pass
diff --git a/erpnext/healthcare/doctype/lab_test_groups/__init__.py b/erpnext/healthcare/doctype/organism_test_item/__init__.py
similarity index 100%
copy from erpnext/healthcare/doctype/lab_test_groups/__init__.py
copy to erpnext/healthcare/doctype/organism_test_item/__init__.py
diff --git a/erpnext/healthcare/doctype/organism_test_item/organism_test_item.json b/erpnext/healthcare/doctype/organism_test_item/organism_test_item.json
new file mode 100644
index 0000000..56d0a4d
--- /dev/null
+++ b/erpnext/healthcare/doctype/organism_test_item/organism_test_item.json
@@ -0,0 +1,144 @@
+{
+ "allow_copy": 0,
+ "allow_events_in_timeline": 0,
+ "allow_guest_to_view": 0,
+ "allow_import": 0,
+ "allow_rename": 0,
+ "beta": 1,
+ "creation": "2019-09-06 16:37:59.698996",
+ "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,
+   "fetch_if_empty": 0,
+   "fieldname": "organism",
+   "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": "Organism",
+   "length": 0,
+   "no_copy": 0,
+   "options": "Organism",
+   "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
+  },
+  {
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fetch_if_empty": 0,
+   "fieldname": "colony_population",
+   "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": "Colony Population",
+   "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": "colony_uom",
+   "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": "Colony UOM",
+   "length": 0,
+   "no_copy": 0,
+   "options": "Lab Test UOM",
+   "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
+  }
+ ],
+ "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-10-04 19:48:04.104234",
+ "modified_by": "Administrator",
+ "module": "Healthcare",
+ "name": "Organism Test Item",
+ "name_case": "",
+ "owner": "Administrator",
+ "permissions": [],
+ "quick_entry": 0,
+ "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/healthcare/doctype/sensitivity_test_items/sensitivity_test_items.py b/erpnext/healthcare/doctype/organism_test_item/organism_test_item.py
similarity index 61%
copy from erpnext/healthcare/doctype/sensitivity_test_items/sensitivity_test_items.py
copy to erpnext/healthcare/doctype/organism_test_item/organism_test_item.py
index 35c8efd..019a55b 100644
--- a/erpnext/healthcare/doctype/sensitivity_test_items/sensitivity_test_items.py
+++ b/erpnext/healthcare/doctype/organism_test_item/organism_test_item.py
@@ -1,9 +1,9 @@
 # -*- coding: utf-8 -*-
-# Copyright (c) 2015, ESS and contributors
+# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
 # For license information, please see license.txt
 
 from __future__ import unicode_literals
 from frappe.model.document import Document
 
-class SensitivityTestItems(Document):
+class OrganismTestItem(Document):
 	pass
diff --git a/erpnext/healthcare/doctype/lab_test_groups/__init__.py b/erpnext/healthcare/doctype/organism_test_result/__init__.py
similarity index 100%
copy from erpnext/healthcare/doctype/lab_test_groups/__init__.py
copy to erpnext/healthcare/doctype/organism_test_result/__init__.py
diff --git a/erpnext/healthcare/doctype/organism_test_result/organism_test_result.json b/erpnext/healthcare/doctype/organism_test_result/organism_test_result.json
new file mode 100644
index 0000000..8b238de
--- /dev/null
+++ b/erpnext/healthcare/doctype/organism_test_result/organism_test_result.json
@@ -0,0 +1,144 @@
+{
+ "allow_copy": 0,
+ "allow_events_in_timeline": 0,
+ "allow_guest_to_view": 0,
+ "allow_import": 0,
+ "allow_rename": 0,
+ "beta": 1,
+ "creation": "2019-09-06 16:37:59.698996",
+ "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,
+   "fetch_if_empty": 0,
+   "fieldname": "organism",
+   "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": "Organism",
+   "length": 0,
+   "no_copy": 0,
+   "options": "Organism",
+   "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
+  },
+  {
+   "allow_bulk_edit": 0,
+   "allow_in_quick_entry": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fetch_if_empty": 0,
+   "fieldname": "colony_population",
+   "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": "Colony Population",
+   "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": "colony_uom",
+   "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": "Colony UOM",
+   "length": 0,
+   "no_copy": 0,
+   "options": "Lab Test UOM",
+   "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
+  }
+ ],
+ "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-10-04 19:48:04.104234",
+ "modified_by": "Administrator",
+ "module": "Healthcare",
+ "name": "Organism Test Result",
+ "name_case": "",
+ "owner": "Administrator",
+ "permissions": [],
+ "quick_entry": 0,
+ "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/selling/doctype/pos_closing_voucher_taxes/pos_closing_voucher_taxes.py b/erpnext/healthcare/doctype/organism_test_result/organism_test_result.py
similarity index 61%
copy from erpnext/selling/doctype/pos_closing_voucher_taxes/pos_closing_voucher_taxes.py
copy to erpnext/healthcare/doctype/organism_test_result/organism_test_result.py
index 87ce842..02393c2 100644
--- a/erpnext/selling/doctype/pos_closing_voucher_taxes/pos_closing_voucher_taxes.py
+++ b/erpnext/healthcare/doctype/organism_test_result/organism_test_result.py
@@ -1,9 +1,9 @@
 # -*- coding: utf-8 -*-
-# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
+# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
 # For license information, please see license.txt
 
 from __future__ import unicode_literals
 from frappe.model.document import Document
 
-class POSClosingVoucherTaxes(Document):
+class OrganismTestResult(Document):
 	pass
diff --git a/erpnext/healthcare/doctype/patient_encounter/patient_encounter.py b/erpnext/healthcare/doctype/patient_encounter/patient_encounter.py
index 56401a3..262fc46 100644
--- a/erpnext/healthcare/doctype/patient_encounter/patient_encounter.py
+++ b/erpnext/healthcare/doctype/patient_encounter/patient_encounter.py
@@ -73,7 +73,7 @@
 		insert_encounter_to_medical_record(encounter)
 
 def delete_medical_record(encounter):
-	frappe.db.delete_doc_if_exists('Patient Medical Record', 'reference_name', encounter.name)
+	frappe.delete_doc_if_exists('Patient Medical Record', 'reference_name', encounter.name)
 
 def set_subject_field(encounter):
 	subject = frappe.bold(_('Healthcare Practitioner: ')) + encounter.practitioner + '<br>'
diff --git a/erpnext/healthcare/doctype/sensitivity_test_items/sensitivity_test_items.json b/erpnext/healthcare/doctype/sensitivity_test_items/sensitivity_test_items.json
deleted file mode 100644
index 86f5e26..0000000
--- a/erpnext/healthcare/doctype/sensitivity_test_items/sensitivity_test_items.json
+++ /dev/null
@@ -1,103 +0,0 @@
-{
- "allow_copy": 1, 
- "allow_guest_to_view": 0, 
- "allow_import": 0, 
- "allow_rename": 0, 
- "beta": 1, 
- "creation": "2016-02-22 15:18:01.769903", 
- "custom": 0, 
- "docstatus": 0, 
- "doctype": "DocType", 
- "document_type": "Document", 
- "editable_grid": 1, 
- "fields": [
-  {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "antibiotic", 
-   "fieldtype": "Link", 
-   "hidden": 0, 
-   "ignore_user_permissions": 1, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Antibiotic", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Antibiotic", 
-   "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
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "antibiotic_sensitivity", 
-   "fieldtype": "Link", 
-   "hidden": 0, 
-   "ignore_user_permissions": 1, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Sensitivity", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Sensitivity", 
-   "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
-  }
- ], 
- "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": "2017-10-05 11:08:06.327972", 
- "modified_by": "Administrator", 
- "module": "Healthcare", 
- "name": "Sensitivity Test Items", 
- "name_case": "", 
- "owner": "Administrator", 
- "permissions": [], 
- "quick_entry": 0, 
- "read_only": 0, 
- "read_only_onload": 0, 
- "restrict_to_domain": "Healthcare", 
- "show_name_in_global_search": 0, 
- "sort_field": "modified", 
- "sort_order": "DESC", 
- "track_changes": 0, 
- "track_seen": 0
-}
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/sensitivity_test_items/__init__.py b/erpnext/healthcare/doctype/sensitivity_test_result/__init__.py
similarity index 100%
rename from erpnext/healthcare/doctype/sensitivity_test_items/__init__.py
rename to erpnext/healthcare/doctype/sensitivity_test_result/__init__.py
diff --git a/erpnext/healthcare/doctype/sensitivity_test_result/sensitivity_test_result.json b/erpnext/healthcare/doctype/sensitivity_test_result/sensitivity_test_result.json
new file mode 100644
index 0000000..768c177
--- /dev/null
+++ b/erpnext/healthcare/doctype/sensitivity_test_result/sensitivity_test_result.json
@@ -0,0 +1,103 @@
+{
+ "allow_copy": 1,
+ "allow_guest_to_view": 0,
+ "allow_import": 0,
+ "allow_rename": 0,
+ "beta": 1,
+ "creation": "2016-02-22 15:18:01.769903",
+ "custom": 0,
+ "docstatus": 0,
+ "doctype": "DocType",
+ "document_type": "Document",
+ "editable_grid": 1,
+ "fields": [
+  {
+   "allow_bulk_edit": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fieldname": "antibiotic",
+   "fieldtype": "Link",
+   "hidden": 0,
+   "ignore_user_permissions": 1,
+   "ignore_xss_filter": 0,
+   "in_filter": 0,
+   "in_global_search": 0,
+   "in_list_view": 1,
+   "in_standard_filter": 0,
+   "label": "Antibiotic",
+   "length": 0,
+   "no_copy": 0,
+   "options": "Antibiotic",
+   "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
+  },
+  {
+   "allow_bulk_edit": 0,
+   "allow_on_submit": 0,
+   "bold": 0,
+   "collapsible": 0,
+   "columns": 0,
+   "fieldname": "antibiotic_sensitivity",
+   "fieldtype": "Link",
+   "hidden": 0,
+   "ignore_user_permissions": 1,
+   "ignore_xss_filter": 0,
+   "in_filter": 0,
+   "in_global_search": 0,
+   "in_list_view": 1,
+   "in_standard_filter": 0,
+   "label": "Sensitivity",
+   "length": 0,
+   "no_copy": 0,
+   "options": "Sensitivity",
+   "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
+  }
+ ],
+ "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": "2017-10-05 11:08:06.327972",
+ "modified_by": "Administrator",
+ "module": "Healthcare",
+ "name": "Sensitivity Test Result",
+ "name_case": "",
+ "owner": "Administrator",
+ "permissions": [],
+ "quick_entry": 0,
+ "read_only": 0,
+ "read_only_onload": 0,
+ "restrict_to_domain": "Healthcare",
+ "show_name_in_global_search": 0,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 0,
+ "track_seen": 0
+}
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/sensitivity_test_items/sensitivity_test_items.py b/erpnext/healthcare/doctype/sensitivity_test_result/sensitivity_test_result.py
similarity index 83%
rename from erpnext/healthcare/doctype/sensitivity_test_items/sensitivity_test_items.py
rename to erpnext/healthcare/doctype/sensitivity_test_result/sensitivity_test_result.py
index 35c8efd..64f1e6c 100644
--- a/erpnext/healthcare/doctype/sensitivity_test_items/sensitivity_test_items.py
+++ b/erpnext/healthcare/doctype/sensitivity_test_result/sensitivity_test_result.py
@@ -5,5 +5,5 @@
 from __future__ import unicode_literals
 from frappe.model.document import Document
 
-class SensitivityTestItems(Document):
+class SensitivityTestResult(Document):
 	pass
diff --git a/erpnext/healthcare/doctype/special_test_items/__init__.py b/erpnext/healthcare/doctype/special_test_items/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/healthcare/doctype/special_test_items/__init__.py
+++ /dev/null
diff --git a/erpnext/healthcare/doctype/special_test_items/special_test_items.json b/erpnext/healthcare/doctype/special_test_items/special_test_items.json
deleted file mode 100644
index a15806e..0000000
--- a/erpnext/healthcare/doctype/special_test_items/special_test_items.json
+++ /dev/null
@@ -1,175 +0,0 @@
-{
- "allow_copy": 1, 
- "allow_guest_to_view": 0, 
- "allow_import": 0, 
- "allow_rename": 0, 
- "beta": 1, 
- "creation": "2016-02-22 15:12:36.202380", 
- "custom": 0, 
- "docstatus": 0, 
- "doctype": "DocType", 
- "document_type": "Document", 
- "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": "lab_test_particulars", 
-   "fieldtype": "Data", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 1, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Particulars", 
-   "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, 
-   "depends_on": "eval:doc.require_result_value == 1", 
-   "fieldname": "result_value", 
-   "fieldtype": "Small Text", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 1, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Value", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "print_width": "", 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0, 
-   "width": ""
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "require_result_value", 
-   "fieldtype": "Check", 
-   "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": "Require Result Value", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 1, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 1, 
-   "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, 
-   "fieldname": "template", 
-   "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": "Template", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Lab Test Template", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 1, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 1, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }
- ], 
- "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-04 12:01:18.801216", 
- "modified_by": "Administrator", 
- "module": "Healthcare", 
- "name": "Special Test Items", 
- "name_case": "", 
- "owner": "Administrator", 
- "permissions": [], 
- "quick_entry": 0, 
- "read_only": 0, 
- "read_only_onload": 0, 
- "restrict_to_domain": "Healthcare", 
- "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/healthcare/doctype/special_test_items/special_test_items.py b/erpnext/healthcare/doctype/special_test_items/special_test_items.py
deleted file mode 100644
index 17080b7..0000000
--- a/erpnext/healthcare/doctype/special_test_items/special_test_items.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# -*- coding: utf-8 -*-
-# Copyright (c) 2015, ESS and contributors
-# For license information, please see license.txt
-
-from __future__ import unicode_literals
-from frappe.model.document import Document
-
-class SpecialTestItems(Document):
-	pass
diff --git a/erpnext/healthcare/doctype/special_test_template/special_test_template.json b/erpnext/healthcare/doctype/special_test_template/special_test_template.json
deleted file mode 100644
index 372af0a..0000000
--- a/erpnext/healthcare/doctype/special_test_template/special_test_template.json
+++ /dev/null
@@ -1,72 +0,0 @@
-{
- "allow_copy": 1, 
- "allow_guest_to_view": 0, 
- "allow_import": 0, 
- "allow_rename": 0, 
- "beta": 1, 
- "creation": "2016-02-22 16:12:12.394200", 
- "custom": 0, 
- "docstatus": 0, 
- "doctype": "DocType", 
- "document_type": "Setup", 
- "editable_grid": 1, 
- "fields": [
-  {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "particulars", 
-   "fieldtype": "Data", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 1, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Result Component", 
-   "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, 
-   "unique": 0
-  }
- ], 
- "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": "2017-10-04 16:20:09.565316", 
- "modified_by": "Administrator", 
- "module": "Healthcare", 
- "name": "Special Test Template", 
- "name_case": "", 
- "owner": "Administrator", 
- "permissions": [], 
- "quick_entry": 0, 
- "read_only": 0, 
- "read_only_onload": 0, 
- "restrict_to_domain": "Healthcare", 
- "show_name_in_global_search": 0, 
- "sort_field": "modified", 
- "sort_order": "DESC", 
- "track_changes": 0, 
- "track_seen": 0
-}
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/therapy_session/therapy_session.json b/erpnext/healthcare/doctype/therapy_session/therapy_session.json
index 00d74a0..c75d934 100644
--- a/erpnext/healthcare/doctype/therapy_session/therapy_session.json
+++ b/erpnext/healthcare/doctype/therapy_session/therapy_session.json
@@ -19,6 +19,7 @@
   "practitioner",
   "department",
   "details_section",
+  "medical_code",
   "duration",
   "rate",
   "location",
@@ -206,11 +207,19 @@
    "fieldtype": "Data",
    "label": "Patient Name",
    "read_only": 1
+  },
+  {
+   "fetch_from": "therapy_type.medical_code",
+   "fieldname": "medical_code",
+   "fieldtype": "Link",
+   "label": "Medical Code",
+   "options": "Medical Code",
+   "read_only": 1
   }
  ],
  "is_submittable": 1,
  "links": [],
- "modified": "2020-04-29 16:49:16.286006",
+ "modified": "2020-06-29 14:33:34.836594",
  "modified_by": "Administrator",
  "module": "Healthcare",
  "name": "Therapy Session",
diff --git a/erpnext/healthcare/doctype/therapy_type/therapy_type.js b/erpnext/healthcare/doctype/therapy_type/therapy_type.js
index 7a61b0d..6e155dc 100644
--- a/erpnext/healthcare/doctype/therapy_type/therapy_type.js
+++ b/erpnext/healthcare/doctype/therapy_type/therapy_type.js
@@ -45,6 +45,16 @@
 
 	medical_department: function(frm) {
 		mark_change_in_item(frm);
+	},
+
+	medical_code: function(frm) {
+		frm.set_query("medical_code", function() {
+			return {
+				filters: {
+					medical_code_standard: frm.doc.medical_code_standard
+				}
+			};
+		});
 	}
 });
 
diff --git a/erpnext/healthcare/doctype/therapy_type/therapy_type.json b/erpnext/healthcare/doctype/therapy_type/therapy_type.json
index 0b3c3ca..f365b1d 100644
--- a/erpnext/healthcare/doctype/therapy_type/therapy_type.json
+++ b/erpnext/healthcare/doctype/therapy_type/therapy_type.json
@@ -22,6 +22,9 @@
   "item_group",
   "column_break_12",
   "description",
+  "medical_coding_section",
+  "medical_code_standard",
+  "medical_code",
   "section_break_18",
   "therapy_for",
   "add_exercises",
@@ -160,10 +163,30 @@
   {
    "fieldname": "section_break_18",
    "fieldtype": "Section Break"
+  },
+  {
+   "collapsible": 1,
+   "fieldname": "medical_coding_section",
+   "fieldtype": "Section Break",
+   "label": "Medical Coding",
+   "options": "Medical Coding"
+  },
+  {
+   "fieldname": "medical_code_standard",
+   "fieldtype": "Link",
+   "label": "Medical Code Standard",
+   "options": "Medical Code Standard"
+  },
+  {
+   "depends_on": "medical_code_standard",
+   "fieldname": "medical_code",
+   "fieldtype": "Link",
+   "label": "Medical Code",
+   "options": "Medical Code"
   }
  ],
  "links": [],
- "modified": "2020-04-21 13:09:04.006289",
+ "modified": "2020-06-29 14:18:50.669951",
  "modified_by": "Administrator",
  "module": "Healthcare",
  "name": "Therapy Type",
diff --git a/erpnext/healthcare/healthcare_dashboard/healthcare/healthcare.json b/erpnext/healthcare/healthcare_dashboard/healthcare/healthcare.json
new file mode 100644
index 0000000..2fea668
--- /dev/null
+++ b/erpnext/healthcare/healthcare_dashboard/healthcare/healthcare.json
@@ -0,0 +1,62 @@
+{
+ "cards": [
+  {
+   "card": "Total Patients"
+  },
+  {
+   "card": "Total Patients Admitted"
+  },
+  {
+   "card": "Open Appointments"
+  },
+  {
+   "card": "Appointments to Bill"
+  }
+ ],
+ "charts": [
+  {
+   "chart": "Patient Appointments",
+   "width": "Full"
+  },
+  {
+   "chart": "In-Patient Status",
+   "width": "Half"
+  },
+  {
+   "chart": "Clinical Procedures Status",
+   "width": "Half"
+  },
+  {
+   "chart": "Lab Tests",
+   "width": "Half"
+  },
+  {
+   "chart": "Clinical Procedures",
+   "width": "Half"
+  },
+  {
+   "chart": "Symptoms",
+   "width": "Half"
+  },
+  {
+   "chart": "Diagnoses",
+   "width": "Half"
+  },
+  {
+   "chart": "Department wise Patient Appointments",
+   "width": "Full"
+  }
+ ],
+ "creation": "2020-07-14 18:17:54.823311",
+ "dashboard_name": "Healthcare",
+ "docstatus": 0,
+ "doctype": "Dashboard",
+ "idx": 0,
+ "is_default": 0,
+ "is_standard": 1,
+ "modified": "2020-07-22 15:36:34.220387",
+ "modified_by": "Administrator",
+ "module": "Healthcare",
+ "name": "Healthcare",
+ "owner": "Administrator"
+}
\ No newline at end of file
diff --git a/erpnext/healthcare/module_onboarding/healthcare/healthcare.json b/erpnext/healthcare/module_onboarding/healthcare/healthcare.json
index 3e50726..56c3c13 100644
--- a/erpnext/healthcare/module_onboarding/healthcare/healthcare.json
+++ b/erpnext/healthcare/module_onboarding/healthcare/healthcare.json
@@ -10,7 +10,7 @@
  "documentation_url": "https://docs.erpnext.com/docs/user/manual/en/healthcare",
  "idx": 0,
  "is_complete": 0,
- "modified": "2020-05-26 23:16:37.603361",
+ "modified": "2020-07-08 14:06:19.512946",
  "modified_by": "Administrator",
  "module": "Healthcare",
  "name": "Healthcare",
@@ -35,8 +35,7 @@
    "step": "Explore Clinical Procedure Templates"
   }
  ],
- "subtitle": "Patients, Practitioner Schedules, Settings and more.",
- "success_message": "Yayy! The Healthcare Module is all set up!",
- "title": "Let's Setup the Healthcare Module",
- "user_can_dismiss": 1
+ "subtitle": "Patients, Practitioner Schedules, Settings, and more.",
+ "success_message": "The Healthcare Module is all set up!",
+ "title": "Let's Set Up the Healthcare Module."
 }
\ No newline at end of file
diff --git a/erpnext/healthcare/number_card/appointments_to_bill/appointments_to_bill.json b/erpnext/healthcare/number_card/appointments_to_bill/appointments_to_bill.json
new file mode 100644
index 0000000..3e4d4e2
--- /dev/null
+++ b/erpnext/healthcare/number_card/appointments_to_bill/appointments_to_bill.json
@@ -0,0 +1,21 @@
+{
+ "creation": "2020-07-14 18:17:54.792773",
+ "docstatus": 0,
+ "doctype": "Number Card",
+ "document_type": "Patient Appointment",
+ "dynamic_filters_json": "[[\"Patient Appointment\",\"company\",\"=\",\"frappe.defaults.get_user_default(\\\"Company\\\")\"]]",
+ "filters_json": "[[\"Patient Appointment\",\"invoiced\",\"=\",0,false]]",
+ "function": "Count",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "label": "Appointments To Bill",
+ "modified": "2020-07-22 13:27:58.038577",
+ "modified_by": "Administrator",
+ "module": "Healthcare",
+ "name": "Appointments to Bill",
+ "owner": "Administrator",
+ "show_percentage_stats": 1,
+ "stats_time_interval": "Daily",
+ "type": "Document Type"
+}
\ No newline at end of file
diff --git a/erpnext/healthcare/number_card/open_appointments/open_appointments.json b/erpnext/healthcare/number_card/open_appointments/open_appointments.json
new file mode 100644
index 0000000..8d121cc
--- /dev/null
+++ b/erpnext/healthcare/number_card/open_appointments/open_appointments.json
@@ -0,0 +1,21 @@
+{
+ "creation": "2020-07-14 18:17:54.771092",
+ "docstatus": 0,
+ "doctype": "Number Card",
+ "document_type": "Patient Appointment",
+ "dynamic_filters_json": "[[\"Patient Appointment\",\"company\",\"=\",\"frappe.defaults.get_user_default(\\\"Company\\\")\"]]",
+ "filters_json": "[[\"Patient Appointment\",\"status\",\"=\",\"Open\",false]]",
+ "function": "Count",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "label": "Open Appointments",
+ "modified": "2020-07-22 13:27:09.542122",
+ "modified_by": "Administrator",
+ "module": "Healthcare",
+ "name": "Open Appointments",
+ "owner": "Administrator",
+ "show_percentage_stats": 1,
+ "stats_time_interval": "Daily",
+ "type": "Document Type"
+}
\ No newline at end of file
diff --git a/erpnext/healthcare/number_card/total_patients/total_patients.json b/erpnext/healthcare/number_card/total_patients/total_patients.json
new file mode 100644
index 0000000..75441a6
--- /dev/null
+++ b/erpnext/healthcare/number_card/total_patients/total_patients.json
@@ -0,0 +1,20 @@
+{
+ "creation": "2020-07-14 18:17:54.727946",
+ "docstatus": 0,
+ "doctype": "Number Card",
+ "document_type": "Patient",
+ "filters_json": "[[\"Patient\",\"status\",\"=\",\"Active\",false]]",
+ "function": "Count",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "label": "Total Patients",
+ "modified": "2020-07-22 13:26:02.643534",
+ "modified_by": "Administrator",
+ "module": "Healthcare",
+ "name": "Total Patients",
+ "owner": "Administrator",
+ "show_percentage_stats": 1,
+ "stats_time_interval": "Daily",
+ "type": "Document Type"
+}
\ No newline at end of file
diff --git a/erpnext/healthcare/number_card/total_patients_admitted/total_patients_admitted.json b/erpnext/healthcare/number_card/total_patients_admitted/total_patients_admitted.json
new file mode 100644
index 0000000..69a967d
--- /dev/null
+++ b/erpnext/healthcare/number_card/total_patients_admitted/total_patients_admitted.json
@@ -0,0 +1,20 @@
+{
+ "creation": "2020-07-14 18:17:54.749754",
+ "docstatus": 0,
+ "doctype": "Number Card",
+ "document_type": "Patient",
+ "filters_json": "[[\"Patient\",\"inpatient_status\",\"=\",\"Admitted\",false]]",
+ "function": "Count",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "label": "Total Patients Admitted",
+ "modified": "2020-07-22 13:26:20.027788",
+ "modified_by": "Administrator",
+ "module": "Healthcare",
+ "name": "Total Patients Admitted",
+ "owner": "Administrator",
+ "show_percentage_stats": 1,
+ "stats_time_interval": "Daily",
+ "type": "Document Type"
+}
\ No newline at end of file
diff --git a/erpnext/healthcare/print_format/lab_test_print/lab_test_print.json b/erpnext/healthcare/print_format/lab_test_print/lab_test_print.json
index e8e95d8..f7d1676 100644
--- a/erpnext/healthcare/print_format/lab_test_print/lab_test_print.json
+++ b/erpnext/healthcare/print_format/lab_test_print/lab_test_print.json
@@ -7,16 +7,17 @@
  "docstatus": 0,
  "doctype": "Print Format",
  "font": "Default",
- "html": "<div >\n  {% if letter_head and not no_letterhead -%}\n    <div class=\"letter-head\">{{ letter_head }}</div>\n    <hr>\n  {%- endif %}\n\n  {% if (doc.docstatus != 1) %}\n  <b>Lab Tests have to be Submitted for Print .. !</b>\n  {% elif (frappe.db.get_value(\"Healthcare Settings\", \"None\", \"lab_test_approval_required\") == '1' and doc.approval_status != \"Approved\") %}\n  <b>Lab Tests have to be Approved for Print .. !</b>\n  {%- else -%}\n  <div class=\"row section-break\">\n    <div class=\"col-xs-6 column-break\">\n\n      <div class=\"row\">\n        <div class=\"col-xs-4 text-left\">\n          <label>Patient</label>\n        </div>\n        {% if doc.patient %}\n        <div class=\"col-xs-7  value\">\n          <strong>: </strong>{{doc.patient}}\n        </div>\n        {% else %}\n        <div class=\"col-xs-7  value\">\n          <strong>: </strong><em>Patient Name</em>\n        </div>\n        {%- endif -%}\n      </div>\n\n      <div class=\"row\">\n        <div class=\"col-xs-4 text-left\">\n          <label>Age</label>\n        </div>\n        <div class=\"col-xs-7  value\">\n          <strong>: </strong> {{doc.patient_age}}\n        </div>\n      </div>\n\n      <div class=\"row\">\n        <div class=\"col-xs-4 text-left\">\n          <label>Gender</label>\n        </div>\n        <div class=\"col-xs-7  value\">\n          <strong>: </strong> {{doc.patient_sex}}\n        </div>\n      </div>\n\n    </div>\n\n    <div class=\"col-xs-6 column-break\">\n\n      <div class=\"row\">\n        <div class=\"col-xs-4 text-left\">\n          <label>Practitioner</label>\n        </div>\n        {% if doc.practitioner %}\n        <div class=\"col-xs-7  text-left value\">\n          <strong>: </strong>{{doc.practitioner}}\n        </div>\n        {%- endif -%}\n      </div>\n\n      {% if doc.sample_date %}\n      <div class=\"row\">\n        <div class=\"col-xs-4 text-left\">\n          <label>Sample Date</label>\n        </div>\n        <div class=\"col-xs-7 text-left value\">\n          <strong>: </strong>{{doc.sample_date}}\n        </div>\n      </div>\n      {%- endif -%}\n\n      {% if doc.result_date %}\n      <div class=\"row\">\n        <div class=\"col-xs-4 text-left\">\n          <label>Result Date</label>\n        </div>\n        <div class=\"col-xs-7 text-left value\">\n          <strong>: </strong>{{doc.result_date}}\n        </div>\n      </div>\n      {%- endif -%}\n\n    </div>\n\n  </div>\n\n  <div align=\"center\">\n    <hr><h4 class=\"text-uppercase\"><b><u>Department of {{doc.department}}</u></b></h4>\n  </div>\n\n  <table class=\"table\">\n    <tbody>\n      {%- if doc.normal_test_items -%}\n      <tr>\n        <th>Name of Test</th>\n        <th class=\"text-left\">Result</th>\n        <th class=\"text-right\">Normal Range</th>\n      </tr>\n\n      {%- if doc.normal_test_items|length > 1 %}\n      <tr><td style=\"width: 40%;\"> <b>{{ doc.lab_test_name }}</b> </td><td></td></tr>\n      {%- endif -%}\n\n      {%- for row in doc.normal_test_items -%}\n      <tr>\n        <td style=\"width: 40%;border:none;\">\n          {%- if doc.normal_test_items|length > 1 %}&emsp;&emsp;{%- endif -%}\n          {%- if row.lab_test_name -%}<b>{{ row.lab_test_name }}</b>\n          {%- else -%}&emsp;&emsp;&emsp;{%- endif -%}\n          {%- if row.lab_test_event -%} &emsp;&emsp;{{ row.lab_test_event }}{%- endif -%}\n        </td>\n\n        <td style=\"width: 20%;text-align: left;border:none;\">\n          {%- if row.result_value -%}{{ row.result_value }}{%- endif -%}&emsp;\n          {%- if row.lab_test_uom -%}{{ row.lab_test_uom }}{%- endif -%}\n        </td>\n\n        <td style=\"width: 30%;text-align: right;border:none;\">\n          <div style=\"border: 0px;\">\n            {%- if row.normal_range -%}{{ row.normal_range }}{%- endif -%}\n          </div>\n        </td>\n      </tr>\n\n      {%- endfor -%}\n      {%- endif -%}\n    </tbody>\n  </table>\n\n  <table class=\"table\">\n    <tbody>\n      {%- if doc.special_test_items -%}\n      <tr>\n        <th>Name of Test</th>\n        <th class=\"text-left\">Result</th>\n      </tr>\n      <tr><td style=\"width: 30%;border:none;\"> <b>{{ doc.lab_test_name }}</b> </td><td></td></tr>\n      {%- for row in doc.special_test_items -%}\n      <tr>\n        <td style=\"width: 30%;border:none;\"> &emsp;&emsp;{{ row.lab_test_particulars }} </td>\n        <td style=\"width: 70%;text-align: left;border:none;\">\n          {%- if row.result_value -%}{{ row.result_value }}{%- endif -%}\n        </td>\n      </tr>\n\n      {%- endfor -%}\n      {%- endif -%}\n\n      {%- if doc.sensitivity_test_items -%}\n      <tr>\n        <th>Antibiotic</th>\n        <th class=\"text-left\">Sensitivity</th>\n      </tr>\n      {%- for row in doc.sensitivity_test_items -%}\n      <tr>\n        <td style=\"width: 30%;border:none;\"> {{ row.antibiotic }} </td>\n        <td style=\"width: 70%;text-align: left;border:none;\">{{ row.antibiotic_sensitivity }}</td>\n      </tr>\n\n      {%- endfor -%}\n      {%- endif -%}\n\n    </tbody>\n  </table>\n  {%- endif -%}\n\n  <div align=\"right\">\n    {%- if (frappe.db.get_value(\"Healthcare Settings\", \"None\", \"employee_name_and_designation_in_print\") == '1') -%}\n    <h6 class=\"text-uppercase\"><b>{{doc.employee_name}}</b></h6>\n    <h6 class=\"text-uppercase\"><b>{{doc.employee_designation}}</b></h6>\n    {%- else -%}\n    <h6 ><b>{{frappe.db.get_value(\"Healthcare Settings\", \"None\", \"custom_signature_in_print\") }}</b></h6>\n    {%- endif -%}\n  </div>\n</div>\n",
+ "html": "<div >\n  {% if letter_head and not no_letterhead -%}\n    <div class=\"letter-head\">{{ letter_head }}</div>\n    <hr>\n  {%- endif %}\n\n  {% if (doc.docstatus != 1) %}\n  <div><h2 class=\"text-uppercase text-center\"><b>WORKSHEET</b></h2></div>\n\t<br/>\n\t<div class=\"row section-break\">\n    <div class=\"col-xs-6 column-break\">\n\n      <div class=\"row\">\n        <div class=\"col-xs-4 text-left\">\n          <label>Patient</label>\n        </div>\n        {% if doc.patient_name %}\n        <div class=\"col-xs-7  value\">\n          {{ doc.patient_name }}\n        </div>\n        {% else %}\n        <div class=\"col-xs-7  value\">\n          {{ doc.patient }}\n        </div>\n        {%- endif -%}\n      </div>\n\n      <div class=\"row\">\n        <div class=\"col-xs-4 text-left\">\n          <label>Age</label>\n        </div>\n        <div class=\"col-xs-7  value\">\n          {{ doc.patient_age or '' }}\n        </div>\n      </div>\n\n      <div class=\"row\">\n        <div class=\"col-xs-4 text-left\">\n          <label>Gender</label>\n        </div>\n        <div class=\"col-xs-7  value\">\n          {{ doc.patient_sex or '' }}\n        </div>\n      </div>\n\n    </div>\n\n    <div class=\"col-xs-6 column-break\">\n\n      <div class=\"row\">\n        <div class=\"col-xs-4 text-left\">\n          <label>Practitioner</label>\n        </div>\n        {% if doc.practitioner_name %}\n        <div class=\"col-xs-7  text-left value\">\n          {{ doc.practitioner_name }}\n        </div>\n        {% else %}\n\t\t\t{% if doc.referring_practitioner_name %}\n            <div class=\"col-xs-7  text-left value\">\n            {{ doc.referring_practitioner_name }}\n            </div>\n\t\t    {% endif %}\n        {%- endif -%}\n      </div>\n\n      {% if doc.sample_date %}\n      <div class=\"row\">\n        <div class=\"col-xs-4 text-left\">\n          <label>Sample Date</label>\n        </div>\n        <div class=\"col-xs-7 text-left value\">\n        {{ doc.sample_date }}\n        </div>\n      </div>\n      {%- endif -%}\n    </div>\n  </div>\n\n\t<div>\n    <hr><h4 class=\"text-uppercase text-center\"><b><u>Department of {{ doc.department }}</u></b></h4>\n  </div>\n\n\t<table class=\"table\">\n    <tbody>\n      {%- if doc.normal_test_items -%}\n      <tr>\n        <th>Name of Test</th>\n        <th class=\"text-left\">Result</th>\n        <th class=\"text-right\">Normal Range</th>\n      </tr>\n\n      {%- if doc.normal_test_items|length > 1 %}\n      <tr><td style=\"width: 40%;\"> <b>{{ doc.lab_test_name }}</b> </td><td></td></tr>\n      {%- endif -%}\n\n      {%- for row in doc.normal_test_items -%}\n      <tr>\n        <td style=\"width: 40%;border:none;\">\n          {%- if doc.normal_test_items|length > 1 %}&emsp;&emsp;{%- endif -%}\n          {%- if row.lab_test_name -%}<b>{{ row.lab_test_name }}</b>\n          {%- else -%}&emsp;&emsp;&emsp;{%- endif -%}\n          {%- if row.lab_test_event -%} &emsp;&emsp;{{ row.lab_test_event }}{%- endif -%}\n        </td>\n\n        <td style=\"width: 20%;text-align: right;border:none;\">\n          {%- if row.lab_test_uom -%}&nbsp;{{ row.lab_test_uom }}{%- endif -%}\n        </td>\n\n        <td style=\"width: 30%;text-align: right;border:none;\">\n          <div style=\"border: 0px;\">\n            {%- if row.normal_range -%}{{ row.normal_range }}{%- endif -%}\n          </div>\n        </td>\n      </tr>\n\n      {%- endfor -%}\n      {%- endif -%}\n    </tbody>\n  </table>\n\n\t<table class=\"table\">\n    <tbody>\n      {%- if doc.descriptive_test_items -%}\n      <tr>\n        <th>Name of Test</th>\n        <th class=\"text-left\">Result</th>\n      </tr>\n      <tr><td style=\"width: 30%;border:none;\"> <b>{{ doc.lab_test_name }}</b> </td><td></td></tr>\n\t\t\t{% set gr_lab_test_name = {'ltname': ''} %}\n      {%- for row in doc.descriptive_test_items -%}\n\t\t\t{%- if row.lab_test_name -%}\n\t\t\t{%- if row.lab_test_name != gr_lab_test_name.ltname -%}\n\t\t\t<tr>\n\t\t\t\t<td style=\"width: 30%;border:none;\"> &emsp;{{ row.lab_test_name }} </td>\n\t\t\t\t<td style=\"width: 70%;text-align: left;border:none;\"></td>\n\t\t\t</tr>\n\t\t\t{% if gr_lab_test_name.update({'ltname': row.lab_test_name}) %} {% endif %}\n\t\t\t{%- endif -%}\n\t\t\t{%- endif -%}\n      <tr>\n        <td style=\"width: 30%;border:none;\"> &emsp;&emsp;{{ row.lab_test_particulars }} </td>\n        <td style=\"width: 70%;text-align: left;border:none;\"></td>\n      </tr>\n      {%- endfor -%}\n      {%- endif -%}\n    </tbody>\n  </table>\n  <div>\n    {% if doc.worksheet_instructions %}\n    <hr>\n    <b>Instructions</b>\n    {{ doc.worksheet_instructions }}\n    {%- endif -%}\n</div>\n  {% elif (frappe.db.get_value(\"Healthcare Settings\", \"None\", \"require_test_result_approval\") == '1' and doc.status != \"Approved\") %}\n  <b>Lab Tests have to be Approved for Print .. !</b>\n  {%- else -%}\n  <div class=\"row section-break\">\n    <div class=\"col-xs-6 column-break\">\n\n      <div class=\"row\">\n        <div class=\"col-xs-4 text-left\">\n          <label>Patient</label>\n        </div>\n        {% if doc.patient_name %}\n        <div class=\"col-xs-7  value\">\n          {{ doc.patient_name }}\n        </div>\n        {% else %}\n        <div class=\"col-xs-7  value\">\n            {{ doc.patient }}\n        </div>\n        {%- endif -%}\n      </div>\n\n      <div class=\"row\">\n        <div class=\"col-xs-4 text-left\">\n          <label>Age</label>\n        </div>\n        <div class=\"col-xs-7  value\">\n        {{ doc.patient_age or '' }}\n        </div>\n      </div>\n\n      <div class=\"row\">\n        <div class=\"col-xs-4 text-left\">\n          <label>Gender</label>\n        </div>\n        <div class=\"col-xs-7  value\">\n          {{ doc.patient_sex or '' }}\n        </div>\n      </div>\n\n    </div>\n\n    <div class=\"col-xs-6 column-break\">\n\n      <div class=\"row\">\n        <div class=\"col-xs-4 text-left\">\n          <label>Practitioner</label>\n        </div>\n        {% if doc.practitioner_name %}\n        <div class=\"col-xs-7  text-left value\">\n          {{ doc.practitioner_name }}\n        </div>\n\t\t{% else %}\n\t\t    {% if doc.referring_practitioner_name %}\n                <div class=\"col-xs-7  text-left value\">\n                {{ doc.referring_practitioner_name }}\n                </div>\n\t\t\t{% endif %}\n        {%- endif -%}\n      </div>\n\n      {% if doc.sample_date %}\n      <div class=\"row\">\n        <div class=\"col-xs-4 text-left\">\n          <label>Sample Date</label>\n        </div>\n        <div class=\"col-xs-7 text-left value\">\n          {{ doc.sample_date }}\n        </div>\n      </div>\n      {%- endif -%}\n\n      {% if doc.result_date %}\n      <div class=\"row\">\n        <div class=\"col-xs-4 text-left\">\n          <label>Result Date</label>\n        </div>\n        <div class=\"col-xs-7 text-left value\">\n          {{ doc.result_date }}\n        </div>\n      </div>\n      {%- endif -%}\n\n    </div>\n\n  </div>\n\n  <div>\n    <hr><h4 class=\"text-uppercase text-center\"><b><u>Department of {{ doc.department }}</u></b></h4>\n  </div>\n\n\t<div>\n\t\t{% if doc.result_legend and  (doc.legend_print_position == \"Top\" or doc.legend_print_position == \"Both\")%}\n\t\t<b>Result Legend:</b>\n\t\t{{ doc.result_legend }}\n\t\t{%- endif -%}\n\t</div>\n\n  <table class=\"table\">\n    <tbody>\n      {%- if doc.normal_test_items -%}\n      <tr>\n        <th>Name of Test</th>\n        <th class=\"text-left\">Result</th>\n        <th class=\"text-right\">Normal Range</th>\n      </tr>\n\n      {%- if doc.normal_test_items|length > 1 %}\n      <tr><td style=\"width: 40%;\"> <b>{{ doc.lab_test_name }}</b> </td><td></td></tr>\n      {%- endif -%}\n\n      {%- for row in doc.normal_test_items -%}\n      <tr>\n        <td style=\"width: 40%;border:none;\">\n          {%- if doc.normal_test_items|length > 1 %}&emsp;&emsp;{%- endif -%}\n          {%- if row.lab_test_name -%}<b>{{ row.lab_test_name }}</b>\n          {%- else -%}&emsp;&emsp;&emsp;{%- endif -%}\n          {%- if row.lab_test_event -%} &emsp;&emsp;{{ row.lab_test_event }}{%- endif -%}\n        </td>\n\n        <td style=\"width: 20%;text-align: left;border:none;\">\n\t\t\t\t\t{%- if row.result_value -%}\n\t\t\t\t\t\t{%- if row.bold -%}<b>{% endif %}\n\t\t\t\t\t\t{%- if row.underline -%}<u>{% endif %}\n\t\t\t\t\t\t{%- if row.italic -%}<i>{% endif %}\n                        {{ row.result_value }}\n                        {%- if row.lab_test_uom -%}&emsp;{{ row.lab_test_uom }}{%- endif -%}\n\t\t\t\t\t\t{%- if row.italic -%}</i>{% endif %}\n\t\t\t\t\t\t{%- if row.underline -%}</u>{% endif %}\n\t\t\t\t\t\t{%- if row.bold -%}</b>{% endif %}\n\t\t\t\t\t{%- endif -%}\n          \n\t\t\t\t\t{%- if row.secondary_uom and row.conversion_factor and row.secondary_uom_result -%}\n\t\t\t\t\t\t<br/>\n\t\t\t\t\t\t{%- if row.bold -%}<b>{% endif %}\n\t\t\t\t\t\t{%- if row.underline -%}<u>{% endif %}\n\t\t\t\t\t\t{%- if row.italic -%}<i>{% endif %}\n                        {{ row.secondary_uom_result }}\n                        &emsp;{{ row.secondary_uom }}\n\t\t\t\t\t\t{%- if row.italic -%}</i>{% endif %}\n\t\t\t\t\t\t{%- if row.underline -%}</u>{% endif %}\n\t\t\t\t\t\t{%- if row.bold -%}</b>{% endif %}\n\t\t\t\t\t\t&emsp;\n\t\t\t\t\t{%- endif -%}\n        </td>\n\n        <td style=\"width: 30%;text-align: right;border:none;\">\n          <div style=\"border: 0px;\">\n            {%- if row.normal_range -%}{{ row.normal_range }}{%- endif -%}\n          </div>\n        </td>\n      </tr>\n\n      {%- endfor -%}\n      {%- endif -%}\n    </tbody>\n  </table>\n\n  <table class=\"table\">\n    <tbody>\n      {%- if doc.descriptive_test_items -%}\n      <tr>\n        <th>Name of Test</th>\n        <th class=\"text-left\">Result</th>\n      </tr>\n      <tr><td style=\"width: 30%;border:none;\"> <b>{{ doc.lab_test_name }}</b> </td><td></td></tr>\n\t\t\t{% set gr_lab_test_name = {'ltname': ''} %}\n      {%- for row in doc.descriptive_test_items -%}\n\t\t\t{%- if row.lab_test_name -%}\n\t\t\t{%- if row.lab_test_name != gr_lab_test_name.ltname -%}\n\t\t\t<tr>\n\t\t\t\t<td style=\"width: 30%;border:none;\"> &emsp;{{ row.lab_test_name }} </td>\n\t\t\t\t<td style=\"width: 70%;text-align: left;border:none;\"></td>\n\t\t\t</tr>\n\t\t\t{% if gr_lab_test_name.update({'ltname': row.lab_test_name}) %} {% endif %}\n\t\t\t{%- endif -%}\n\t\t\t{%- endif -%}\n      <tr>\n        <td style=\"width: 30%;border:none;\"> &emsp;&emsp;{{ row.lab_test_particulars }} </td>\n        <td style=\"width: 70%;text-align: left;border:none;\">\n          {%- if row.result_value -%}{{ row.result_value }}{%- endif -%}\n        </td>\n      </tr>\n      {%- endfor -%}\n      {%- endif -%}\n\n\t\t\t{%- if doc.organisms -%}\n\t\t\t<tr>\n\t\t\t\t<th>Organism</th>\n\t\t\t\t<th class=\"text-left\">Colony Population</th>\n\t\t\t</tr>\n\t\t\t{%- for row in doc.organisms -%}\n\t\t\t<tr>\n\t\t\t\t<td style=\"width: 30%;border:none;\"> {{ row.organism }} </td>\n\t\t\t\t<td style=\"width: 60%;text-align: left;border:none;\">\n\t\t\t\t\t{{ row.colony_population }}\n\t\t\t\t\t{% if row.colony_uom %}\n\t\t\t\t\t\t{{ row.colony_uom }}\n\t\t\t\t\t{% endif %}\n\t\t\t\t</td>\n\t\t\t</tr>\n\t\t\t{%- endfor -%}\n\t\t\t{%- endif -%}\n\n\t\t\t{%- if doc.sensitivity_test_items -%}\n\t\t\t<tr>\n\t\t\t\t<th>Antibiotic</th>\n\t\t\t\t<th class=\"text-left\">Sensitivity</th>\n\t\t\t</tr>\n\t\t\t{%- for row in doc.sensitivity_test_items -%}\n\t\t\t<tr>\n\t\t\t\t<td style=\"width: 30%;border:none;\"> {{ row.antibiotic }} </td>\n\t\t\t\t<td style=\"width: 70%;text-align: left;border:none;\">{{ row.antibiotic_sensitivity }}</td>\n\t\t\t</tr>\n\t\t\t{%- endfor -%}\n\t\t\t{%- endif -%}\n\n    </tbody>\n  </table>\n  <div>\n    {% if doc.custom_result %}\n        <br/>\n        <div> {{ doc.custom_result }} </div>\n    {%- endif -%}\n    </div>\n\n    <div>\n        {% if doc.lab_test_comment %}\n        <br/>\n        <b>Comments</b>\n        {{ doc.lab_test_comment }}\n        {%- endif -%}\n    </div>\n\n    <div class=\"text-right\">\n        {%- if (frappe.db.get_value(\"Healthcare Settings\", \"None\", \"employee_name_and_designation_in_print\") == '1') -%}\n            {%- if doc.employee_name -%}\n            <h6 class=\"text-uppercase\"><b>{{ doc.employee_name }}</b></h6>\n            {%- endif -%}\n            {%- if doc.employee_designation -%}\n            <h6 class=\"text-uppercase\"><b>{{ doc.employee_designation }}</b></h6>\n            {%- endif -%}\n        {%- else -%}\n            {%- if frappe.db.get_value(\"Healthcare Settings\", \"None\", \"custom_signature_in_print\") -%}\n            <h6 ><b>{{ frappe.db.get_value(\"Healthcare Settings\", \"None\", \"custom_signature_in_print\") }}</b></h6>\n            {%- endif -%}\n        {%- endif -%}\n    </div>\n\n    <div>\n        {% if doc.result_legend and  (doc.legend_print_position == \"Bottom\" or doc.legend_print_position == \"Both\" or doc.legend_print_position == \"\")%}\n        <hr>\n        <b>Result Legend</b>\n        {{ doc.result_legend }}\n        {%- endif -%}\n    </div>\n  {%- endif -%}\n</div>",
  "idx": 0,
  "line_breaks": 0,
- "modified": "2018-09-04 12:03:47.066918",
+ "modified": "2020-07-08 15:34:28.866798",
  "modified_by": "Administrator",
  "module": "Healthcare",
  "name": "Lab Test Print",
  "owner": "Administrator",
  "print_format_builder": 0,
- "print_format_type": "Server",
+ "print_format_type": "Jinja",
+ "raw_printing": 0,
  "show_section_headings": 0,
  "standard": "Yes"
 }
\ No newline at end of file
diff --git a/erpnext/healthcare/web_form/lab_test/lab_test.json b/erpnext/healthcare/web_form/lab_test/lab_test.json
index 88a9756..3509917 100644
--- a/erpnext/healthcare/web_form/lab_test/lab_test.json
+++ b/erpnext/healthcare/web_form/lab_test/lab_test.json
@@ -1,255 +1,459 @@
 {
- "accept_payment": 0, 
- "allow_comments": 0, 
- "allow_delete": 0, 
- "allow_edit": 1, 
- "allow_incomplete": 0, 
- "allow_multiple": 1, 
- "allow_print": 1, 
- "amount": 0.0, 
- "amount_based_on_field": 0, 
- "creation": "2017-06-06 16:12:33.052258", 
- "currency": "INR", 
- "doc_type": "Lab Test", 
- "docstatus": 0, 
- "doctype": "Web Form", 
- "idx": 0, 
- "introduction_text": "Lab Test", 
- "is_standard": 1, 
- "login_required": 1, 
- "max_attachment_size": 0, 
- "modified": "2018-09-04 08:50:41.314546", 
- "modified_by": "Administrator", 
- "module": "Healthcare", 
- "name": "lab-test", 
- "owner": "Administrator", 
- "payment_button_label": "Buy Now", 
- "print_format": "Lab Test Print", 
- "published": 1, 
- "route": "lab-test", 
- "show_in_grid": 0, 
- "show_sidebar": 1, 
- "sidebar_items": [], 
- "success_url": "/lab-test", 
- "title": "Lab Test", 
+ "accept_payment": 0,
+ "allow_comments": 1,
+ "allow_delete": 0,
+ "allow_edit": 1,
+ "allow_incomplete": 0,
+ "allow_multiple": 1,
+ "allow_print": 1,
+ "amount": 0.0,
+ "amount_based_on_field": 0,
+ "creation": "2017-06-06 16:12:33.052258",
+ "currency": "INR",
+ "doc_type": "Lab Test",
+ "docstatus": 0,
+ "doctype": "Web Form",
+ "idx": 0,
+ "introduction_text": "Lab Test",
+ "is_standard": 1,
+ "login_required": 1,
+ "max_attachment_size": 0,
+ "modified": "2020-06-22 12:59:49.126398",
+ "modified_by": "Administrator",
+ "module": "Healthcare",
+ "name": "lab-test",
+ "owner": "Administrator",
+ "payment_button_label": "Buy Now",
+ "print_format": "Lab Test Print",
+ "published": 1,
+ "route": "lab-test",
+ "route_to_success_link": 0,
+ "show_attachments": 0,
+ "show_in_grid": 0,
+ "show_sidebar": 1,
+ "sidebar_items": [],
+ "success_url": "/lab-test",
+ "title": "Lab Test",
  "web_form_fields": [
   {
-   "fieldname": "naming_series", 
-   "fieldtype": "Select", 
-   "hidden": 0, 
-   "label": "Series", 
-   "max_length": 0, 
-   "max_value": 0, 
-   "options": "LP-", 
-   "read_only": 0, 
-   "reqd": 1, 
+   "allow_read_on_all_link_options": 0,
+   "fieldname": "lab_test_name",
+   "fieldtype": "Data",
+   "hidden": 0,
+   "label": "Test Name",
+   "max_length": 0,
+   "max_value": 0,
+   "read_only": 1,
+   "reqd": 0,
    "show_in_filter": 0
-  }, 
+  },
   {
-   "default": "0", 
-   "fieldname": "invoiced", 
-   "fieldtype": "Check", 
-   "hidden": 0, 
-   "label": "Invoiced", 
-   "max_length": 0, 
-   "max_value": 0, 
-   "options": "", 
-   "read_only": 0, 
-   "reqd": 0, 
+   "allow_read_on_all_link_options": 0,
+   "fieldname": "department",
+   "fieldtype": "Link",
+   "hidden": 0,
+   "label": "Department",
+   "max_length": 0,
+   "max_value": 0,
+   "options": "Medical Department",
+   "read_only": 1,
+   "reqd": 0,
    "show_in_filter": 0
-  }, 
+  },
   {
-   "fieldname": "patient", 
-   "fieldtype": "Link", 
-   "hidden": 0, 
-   "label": "Patient", 
-   "max_length": 0, 
-   "max_value": 0, 
-   "options": "Patient", 
-   "read_only": 0, 
-   "reqd": 1, 
+   "allow_read_on_all_link_options": 0,
+   "fieldname": "column_break_26",
+   "fieldtype": "Column Break",
+   "hidden": 0,
+   "max_length": 0,
+   "max_value": 0,
+   "read_only": 0,
+   "reqd": 0,
    "show_in_filter": 0
-  }, 
+  },
   {
-   "fieldname": "patient_name", 
-   "fieldtype": "Data", 
-   "hidden": 0, 
-   "label": "Patient Name", 
-   "max_length": 0, 
-   "max_value": 0, 
-   "options": "patient.patient_name", 
-   "read_only": 0, 
-   "reqd": 0, 
+   "allow_read_on_all_link_options": 0,
+   "fieldname": "company",
+   "fieldtype": "Link",
+   "hidden": 0,
+   "label": "Company",
+   "max_length": 0,
+   "max_value": 0,
+   "options": "Company",
+   "read_only": 0,
+   "reqd": 0,
    "show_in_filter": 0
-  }, 
+  },
   {
-   "fieldname": "practitioner", 
-   "fieldtype": "Link", 
-   "hidden": 0, 
-   "label": "Healthcare Practitioner", 
-   "max_length": 0, 
-   "max_value": 0, 
-   "options": "Healthcare Practitioner", 
-   "read_only": 0, 
-   "reqd": 0, 
+   "allow_read_on_all_link_options": 0,
+   "fieldname": "status",
+   "fieldtype": "Select",
+   "hidden": 0,
+   "label": "Status",
+   "max_length": 0,
+   "max_value": 0,
+   "options": "Draft\nCompleted\nApproved\nRejected\nCancelled",
+   "read_only": 1,
+   "reqd": 0,
    "show_in_filter": 0
-  }, 
+  },
   {
-   "fieldname": "status", 
-   "fieldtype": "Select", 
-   "hidden": 0, 
-   "label": "Status", 
-   "max_length": 0, 
-   "max_value": 0, 
-   "options": "Draft\nCompleted\nApproved\nRejected\nCancelled", 
-   "read_only": 0, 
-   "reqd": 0, 
+   "allow_read_on_all_link_options": 0,
+   "fieldname": "submitted_date",
+   "fieldtype": "Datetime",
+   "hidden": 0,
+   "label": "Submitted Date",
+   "max_length": 0,
+   "max_value": 0,
+   "read_only": 0,
+   "reqd": 0,
    "show_in_filter": 0
-  }, 
+  },
   {
-   "fieldname": "department", 
-   "fieldtype": "Link", 
-   "hidden": 0, 
-   "label": "Department", 
-   "max_length": 0, 
-   "max_value": 0, 
-   "options": "Medical Department", 
-   "read_only": 0, 
-   "reqd": 0, 
+   "allow_read_on_all_link_options": 0,
+   "fieldname": "sb_first",
+   "fieldtype": "Section Break",
+   "hidden": 0,
+   "max_length": 0,
+   "max_value": 0,
+   "read_only": 0,
+   "reqd": 0,
    "show_in_filter": 0
-  }, 
+  },
   {
-   "fieldname": "sample", 
-   "fieldtype": "Link", 
-   "hidden": 0, 
-   "label": "Sample ID", 
-   "max_length": 0, 
-   "max_value": 0, 
-   "options": "Sample Collection", 
-   "read_only": 0, 
-   "reqd": 0, 
+   "allow_read_on_all_link_options": 0,
+   "fieldname": "patient",
+   "fieldtype": "Link",
+   "hidden": 0,
+   "label": "Patient",
+   "max_length": 0,
+   "max_value": 0,
+   "options": "Patient",
+   "read_only": 0,
+   "reqd": 1,
    "show_in_filter": 0
-  }, 
+  },
   {
-   "default": "", 
-   "fieldname": "result_date", 
-   "fieldtype": "Date", 
-   "hidden": 0, 
-   "label": "Result Date", 
-   "max_length": 0, 
-   "max_value": 0, 
-   "read_only": 0, 
-   "reqd": 0, 
+   "allow_read_on_all_link_options": 0,
+   "fieldname": "patient_name",
+   "fieldtype": "Data",
+   "hidden": 0,
+   "label": "Patient Name",
+   "max_length": 0,
+   "max_value": 0,
+   "read_only": 1,
+   "reqd": 0,
    "show_in_filter": 0
-  }, 
+  },
   {
-   "fieldname": "report_preference", 
-   "fieldtype": "Data", 
-   "hidden": 0, 
-   "label": "Report Preference", 
-   "max_length": 0, 
-   "max_value": 0, 
-   "read_only": 0, 
-   "reqd": 0, 
+   "allow_read_on_all_link_options": 0,
+   "fieldname": "patient_age",
+   "fieldtype": "Data",
+   "hidden": 0,
+   "label": "Age",
+   "max_length": 0,
+   "max_value": 0,
+   "read_only": 1,
+   "reqd": 0,
    "show_in_filter": 0
-  }, 
+  },
   {
-   "fieldname": "lab_test_name", 
-   "fieldtype": "Data", 
-   "hidden": 0, 
-   "label": "Test Name", 
-   "max_length": 0, 
-   "max_value": 0, 
-   "read_only": 0, 
-   "reqd": 0, 
+   "allow_read_on_all_link_options": 0,
+   "fieldname": "patient_sex",
+   "fieldtype": "Link",
+   "hidden": 0,
+   "label": "Gender",
+   "max_length": 0,
+   "max_value": 0,
+   "options": "Gender",
+   "read_only": 0,
+   "reqd": 1,
    "show_in_filter": 0
-  }, 
+  },
   {
-   "fieldname": "normal_test_items", 
-   "fieldtype": "Table", 
-   "hidden": 0, 
-   "max_length": 0, 
-   "max_value": 0, 
-   "options": "Normal Test Items", 
-   "read_only": 1, 
-   "reqd": 0, 
+   "allow_read_on_all_link_options": 0,
+   "fieldname": "inpatient_record",
+   "fieldtype": "Link",
+   "hidden": 0,
+   "label": "Inpatient Record",
+   "max_length": 0,
+   "max_value": 0,
+   "options": "Inpatient Record",
+   "read_only": 1,
+   "reqd": 0,
    "show_in_filter": 0
-  }, 
+  },
   {
-   "fieldname": "special_test_items", 
-   "fieldtype": "Table", 
-   "hidden": 0, 
-   "max_length": 0, 
-   "max_value": 0, 
-   "options": "Special Test Items", 
-   "read_only": 1, 
-   "reqd": 0, 
+   "allow_read_on_all_link_options": 0,
+   "fieldname": "report_preference",
+   "fieldtype": "Data",
+   "hidden": 0,
+   "label": "Report Preference",
+   "max_length": 0,
+   "max_value": 0,
+   "read_only": 1,
+   "reqd": 0,
    "show_in_filter": 0
-  }, 
+  },
   {
-   "fieldname": "sensitivity_test_items", 
-   "fieldtype": "Table", 
-   "hidden": 0, 
-   "max_length": 0, 
-   "max_value": 0, 
-   "options": "Sensitivity Test Items", 
-   "read_only": 1, 
-   "reqd": 0, 
+   "allow_read_on_all_link_options": 0,
+   "fieldname": "email",
+   "fieldtype": "Data",
+   "hidden": 1,
+   "label": "Email",
+   "max_length": 0,
+   "max_value": 0,
+   "read_only": 1,
+   "reqd": 0,
    "show_in_filter": 0
-  }, 
+  },
   {
-   "fieldname": "lab_test_comment", 
-   "fieldtype": "Text", 
-   "hidden": 0, 
-   "label": "Comments", 
-   "max_length": 0, 
-   "max_value": 0, 
-   "read_only": 1, 
-   "reqd": 0, 
+   "allow_read_on_all_link_options": 0,
+   "fieldname": "mobile",
+   "fieldtype": "Data",
+   "hidden": 1,
+   "label": "Mobile",
+   "max_length": 0,
+   "max_value": 0,
+   "read_only": 1,
+   "reqd": 0,
    "show_in_filter": 0
-  }, 
+  },
   {
-   "fieldname": "custom_result", 
-   "fieldtype": "Text Editor", 
-   "hidden": 0, 
-   "label": "Custom Result", 
-   "max_length": 0, 
-   "max_value": 0, 
-   "read_only": 1, 
-   "reqd": 0, 
+   "allow_read_on_all_link_options": 0,
+   "fieldname": "c_b",
+   "fieldtype": "Column Break",
+   "hidden": 0,
+   "max_length": 0,
+   "max_value": 0,
+   "read_only": 0,
+   "reqd": 0,
    "show_in_filter": 0
-  }, 
+  },
   {
-   "default": "0", 
-   "fieldname": "sensitivity_toggle", 
-   "fieldtype": "Check", 
-   "hidden": 1, 
-   "max_length": 0, 
-   "max_value": 0, 
-   "read_only": 0, 
-   "reqd": 0, 
+   "allow_read_on_all_link_options": 0,
+   "fieldname": "practitioner",
+   "fieldtype": "Link",
+   "hidden": 0,
+   "label": "Requesting Practitioner",
+   "max_length": 0,
+   "max_value": 0,
+   "options": "Healthcare Practitioner",
+   "read_only": 0,
+   "reqd": 0,
    "show_in_filter": 0
-  }, 
+  },
   {
-   "default": "0", 
-   "fieldname": "special_toggle", 
-   "fieldtype": "Check", 
-   "hidden": 1, 
-   "max_length": 0, 
-   "max_value": 0, 
-   "read_only": 0, 
-   "reqd": 0, 
+   "allow_read_on_all_link_options": 0,
+   "fieldname": "practitioner_name",
+   "fieldtype": "Data",
+   "hidden": 0,
+   "label": "Requesting Practitioner",
+   "max_length": 0,
+   "max_value": 0,
+   "read_only": 1,
+   "reqd": 0,
    "show_in_filter": 0
-  }, 
+  },
   {
-   "default": "0", 
-   "fieldname": "normal_toggle", 
-   "fieldtype": "Check", 
-   "hidden": 1, 
-   "max_length": 0, 
-   "max_value": 0, 
-   "read_only": 0, 
-   "reqd": 0, 
+   "allow_read_on_all_link_options": 0,
+   "fieldname": "requesting_department",
+   "fieldtype": "Link",
+   "hidden": 0,
+   "label": "Requesting Department",
+   "max_length": 0,
+   "max_value": 0,
+   "options": "Medical Department",
+   "read_only": 1,
+   "reqd": 0,
+   "show_in_filter": 0
+  },
+  {
+   "allow_read_on_all_link_options": 0,
+   "fieldname": "employee",
+   "fieldtype": "Link",
+   "hidden": 0,
+   "label": "Employee (Lab Technician)",
+   "max_length": 0,
+   "max_value": 0,
+   "options": "Employee",
+   "read_only": 0,
+   "reqd": 0,
+   "show_in_filter": 0
+  },
+  {
+   "allow_read_on_all_link_options": 0,
+   "fieldname": "employee_name",
+   "fieldtype": "Data",
+   "hidden": 0,
+   "label": "Lab Technician Name",
+   "max_length": 0,
+   "max_value": 0,
+   "read_only": 1,
+   "reqd": 0,
+   "show_in_filter": 0
+  },
+  {
+   "allow_read_on_all_link_options": 0,
+   "fieldname": "employee_designation",
+   "fieldtype": "Data",
+   "hidden": 0,
+   "label": "Lab Technician Designation",
+   "max_length": 0,
+   "max_value": 0,
+   "read_only": 1,
+   "reqd": 0,
+   "show_in_filter": 0
+  },
+  {
+   "allow_read_on_all_link_options": 0,
+   "fieldname": "sb_normal",
+   "fieldtype": "Section Break",
+   "hidden": 0,
+   "max_length": 0,
+   "max_value": 0,
+   "read_only": 0,
+   "reqd": 0,
+   "show_in_filter": 0
+  },
+  {
+   "allow_read_on_all_link_options": 0,
+   "fieldname": "lab_test_html",
+   "fieldtype": "HTML",
+   "hidden": 0,
+   "max_length": 0,
+   "max_value": 0,
+   "read_only": 0,
+   "reqd": 0,
+   "show_in_filter": 0
+  },
+  {
+   "allow_read_on_all_link_options": 0,
+   "fieldname": "normal_test_items",
+   "fieldtype": "Table",
+   "hidden": 0,
+   "max_length": 0,
+   "max_value": 0,
+   "options": "Normal Test Result",
+   "read_only": 0,
+   "reqd": 0,
+   "show_in_filter": 0
+  },
+  {
+   "allow_read_on_all_link_options": 0,
+   "fieldname": "sb_descriptive",
+   "fieldtype": "Section Break",
+   "hidden": 0,
+   "max_length": 0,
+   "max_value": 0,
+   "read_only": 0,
+   "reqd": 0,
+   "show_in_filter": 0
+  },
+  {
+   "allow_read_on_all_link_options": 0,
+   "fieldname": "descriptive_test_items",
+   "fieldtype": "Table",
+   "hidden": 0,
+   "max_length": 0,
+   "max_value": 0,
+   "options": "Descriptive Test Result",
+   "read_only": 0,
+   "reqd": 0,
+   "show_in_filter": 0
+  },
+  {
+   "allow_read_on_all_link_options": 0,
+   "depends_on": "special_toggle",
+   "fieldname": "organisms_section",
+   "fieldtype": "Section Break",
+   "hidden": 0,
+   "max_length": 0,
+   "max_value": 0,
+   "read_only": 0,
+   "reqd": 0,
+   "show_in_filter": 0
+  },
+  {
+   "allow_read_on_all_link_options": 0,
+   "fieldname": "organisms",
+   "fieldtype": "Table",
+   "hidden": 0,
+   "max_length": 0,
+   "max_value": 0,
+   "options": "Organism Test Result",
+   "read_only": 0,
+   "reqd": 0,
+   "show_in_filter": 0
+  },
+  {
+   "allow_read_on_all_link_options": 0,
+   "fieldname": "sb_sensitivity",
+   "fieldtype": "Section Break",
+   "hidden": 0,
+   "max_length": 0,
+   "max_value": 0,
+   "read_only": 0,
+   "reqd": 0,
+   "show_in_filter": 0
+  },
+  {
+   "allow_read_on_all_link_options": 0,
+   "fieldname": "sensitivity_test_items",
+   "fieldtype": "Table",
+   "hidden": 0,
+   "max_length": 0,
+   "max_value": 0,
+   "options": "Sensitivity Test Result",
+   "read_only": 0,
+   "reqd": 0,
+   "show_in_filter": 0
+  },
+  {
+   "allow_read_on_all_link_options": 0,
+   "fieldname": "sb_comments",
+   "fieldtype": "Section Break",
+   "hidden": 0,
+   "max_length": 0,
+   "max_value": 0,
+   "read_only": 0,
+   "reqd": 0,
+   "show_in_filter": 0
+  },
+  {
+   "allow_read_on_all_link_options": 0,
+   "fieldname": "lab_test_comment",
+   "fieldtype": "Text",
+   "hidden": 0,
+   "label": "Comments",
+   "max_length": 0,
+   "max_value": 0,
+   "read_only": 0,
+   "reqd": 0,
+   "show_in_filter": 0
+  },
+  {
+   "allow_read_on_all_link_options": 0,
+   "fieldname": "sb_customresult",
+   "fieldtype": "Section Break",
+   "hidden": 0,
+   "label": "Custom Result",
+   "max_length": 0,
+   "max_value": 0,
+   "read_only": 0,
+   "reqd": 0,
+   "show_in_filter": 0
+  },
+  {
+   "allow_read_on_all_link_options": 0,
+   "fieldname": "custom_result",
+   "fieldtype": "Text Editor",
+   "hidden": 0,
+   "label": "Custom Result",
+   "max_length": 0,
+   "max_value": 0,
+   "read_only": 0,
+   "reqd": 0,
    "show_in_filter": 0
   }
  ]
diff --git a/erpnext/hooks.py b/erpnext/hooks.py
index 2a69589..95a836f 100644
--- a/erpnext/hooks.py
+++ b/erpnext/hooks.py
@@ -13,7 +13,7 @@
 app_logo_url = '/assets/erpnext/images/erp-icon.svg'
 
 
-develop_version = '12.x.x-develop'
+develop_version = '13.x.x-develop'
 
 app_include_js = "assets/js/erpnext.min.js"
 app_include_css = "assets/css/erpnext.css"
@@ -234,15 +234,22 @@
 		"validate": "erpnext.portal.doctype.products_settings.products_settings.home_page_is_products"
 	},
 	"Sales Invoice": {
-		"on_submit": ["erpnext.regional.create_transaction_log", "erpnext.regional.italy.utils.sales_invoice_on_submit"],
-		"on_cancel": "erpnext.regional.italy.utils.sales_invoice_on_cancel",
+		"on_submit": [
+			"erpnext.regional.create_transaction_log",
+			"erpnext.regional.italy.utils.sales_invoice_on_submit",
+			"erpnext.erpnext_integrations.taxjar_integration.create_transaction"
+		],
+		"on_cancel": [
+			"erpnext.regional.italy.utils.sales_invoice_on_cancel",
+			"erpnext.erpnext_integrations.taxjar_integration.delete_transaction"
+		],
 		"on_trash": "erpnext.regional.check_deletion_permission"
 	},
 	"Purchase Invoice": {
-		"on_submit": "erpnext.regional.india.utils.make_reverse_charge_entries"
+		"validate": "erpnext.regional.india.utils.update_grand_total_for_rcm"
 	},
 	"Payment Entry": {
-		"on_submit": ["erpnext.regional.create_transaction_log", "erpnext.accounts.doctype.payment_request.payment_request.update_payment_req_status"],
+		"on_submit": ["erpnext.regional.create_transaction_log", "erpnext.accounts.doctype.payment_request.payment_request.update_payment_req_status", "erpnext.accounts.doctype.dunning.dunning.resolve_dunning"],
 		"on_trash": "erpnext.regional.check_deletion_permission"
 	},
 	'Address': {
@@ -261,6 +268,9 @@
 	},
 	"Email Unsubscribe": {
 		"after_insert": "erpnext.crm.doctype.email_campaign.email_campaign.unsubscribe_recipient"
+	},
+	('Quotation', 'Sales Order', 'Sales Invoice'): {
+		'validate': ["erpnext.erpnext_integrations.taxjar_integration.set_sales_tax"]
 	}
 }
 
@@ -364,7 +374,8 @@
 		'erpnext.controllers.taxes_and_totals.get_itemised_tax_breakup_data': 'erpnext.regional.india.utils.get_itemised_tax_breakup_data',
 		'erpnext.accounts.party.get_regional_address_details': 'erpnext.regional.india.utils.get_regional_address_details',
 		'erpnext.hr.utils.calculate_annual_eligible_hra_exemption': 'erpnext.regional.india.utils.calculate_annual_eligible_hra_exemption',
-		'erpnext.hr.utils.calculate_hra_exemption_for_period': 'erpnext.regional.india.utils.calculate_hra_exemption_for_period'
+		'erpnext.hr.utils.calculate_hra_exemption_for_period': 'erpnext.regional.india.utils.calculate_hra_exemption_for_period',
+		'erpnext.accounts.doctype.purchase_invoice.purchase_invoice.make_regional_gl_entries': 'erpnext.regional.india.utils.make_regional_gl_entries'
 	},
 	'United Arab Emirates': {
 		'erpnext.controllers.taxes_and_totals.update_itemised_tax_data': 'erpnext.regional.united_arab_emirates.utils.update_itemised_tax_data'
@@ -541,4 +552,4 @@
 		{'doctype': 'Hotel Room Package', 'index': 3},
 		{'doctype': 'Hotel Room Type', 'index': 4}
 	]
-}
+}
\ No newline at end of file
diff --git a/erpnext/hr/dashboard_chart/attendance_count/attendance_count.json b/erpnext/hr/dashboard_chart/attendance_count/attendance_count.json
new file mode 100644
index 0000000..4666aec
--- /dev/null
+++ b/erpnext/hr/dashboard_chart/attendance_count/attendance_count.json
@@ -0,0 +1,27 @@
+{
+ "chart_name": "Attendance Count",
+ "chart_type": "Report",
+ "creation": "2020-07-22 11:56:32.730068",
+ "custom_options": "{\n\t\t\"type\": \"line\",\n\t\t\"axisOptions\": {\n\t\t\t\"shortenYAxisNumbers\": 1\n\t\t},\n\t\t\"tooltipOptions\": {}\n\t}",
+ "docstatus": 0,
+ "doctype": "Dashboard Chart",
+ "dynamic_filters_json": "{\"month\":\"frappe.datetime.str_to_obj(frappe.datetime.get_today()).getMonth() + 1\",\"year\":\"frappe.datetime.str_to_obj(frappe.datetime.get_today()).getFullYear();\",\"company\":\"frappe.defaults.get_user_default(\\\"Company\\\")\"}",
+ "filters_json": "{}",
+ "group_by_type": "Count",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "modified": "2020-07-22 14:32:40.334424",
+ "modified_by": "Administrator",
+ "module": "HR",
+ "name": "Attendance Count",
+ "number_of_groups": 0,
+ "owner": "Administrator",
+ "report_name": "Monthly Attendance Sheet",
+ "time_interval": "Yearly",
+ "timeseries": 0,
+ "timespan": "Last Year",
+ "type": "Line",
+ "use_report_chart": 1,
+ "y_axis": []
+}
\ No newline at end of file
diff --git a/erpnext/hr/dashboard_chart/department_wise_employee_count/department_wise_employee_count.json b/erpnext/hr/dashboard_chart/department_wise_employee_count/department_wise_employee_count.json
new file mode 100644
index 0000000..c21bfb9
--- /dev/null
+++ b/erpnext/hr/dashboard_chart/department_wise_employee_count/department_wise_employee_count.json
@@ -0,0 +1,29 @@
+{
+ "chart_name": "Department Wise Employee Count",
+ "chart_type": "Group By",
+ "creation": "2020-07-22 11:56:32.760730",
+ "custom_options": "",
+ "docstatus": 0,
+ "doctype": "Dashboard Chart",
+ "document_type": "Employee",
+ "dynamic_filters_json": "[[\"Employee\",\"company\",\"=\",\"frappe.defaults.get_user_default(\\\"Company\\\")\"]]",
+ "filters_json": "[[\"Employee\",\"status\",\"=\",\"Active\",false]]",
+ "group_by_based_on": "department",
+ "group_by_type": "Count",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "last_synced_on": "2020-07-22 14:27:40.574194",
+ "modified": "2020-07-22 14:33:38.036794",
+ "modified_by": "Administrator",
+ "module": "HR",
+ "name": "Department Wise Employee Count",
+ "number_of_groups": 0,
+ "owner": "Administrator",
+ "time_interval": "Yearly",
+ "timeseries": 0,
+ "timespan": "Last Year",
+ "type": "Donut",
+ "use_report_chart": 0,
+ "y_axis": []
+}
\ No newline at end of file
diff --git a/erpnext/hr/dashboard_chart/department_wise_openings/department_wise_openings.json b/erpnext/hr/dashboard_chart/department_wise_openings/department_wise_openings.json
new file mode 100644
index 0000000..b1953d4
--- /dev/null
+++ b/erpnext/hr/dashboard_chart/department_wise_openings/department_wise_openings.json
@@ -0,0 +1,29 @@
+{
+ "aggregate_function_based_on": "planned_vacancies",
+ "chart_name": "Department Wise Openings",
+ "chart_type": "Group By",
+ "creation": "2020-07-22 11:56:32.849775",
+ "custom_options": "",
+ "docstatus": 0,
+ "doctype": "Dashboard Chart",
+ "document_type": "Job Opening",
+ "filters_json": "[]",
+ "group_by_based_on": "department",
+ "group_by_type": "Sum",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "last_synced_on": "2020-07-22 14:33:44.834801",
+ "modified": "2020-07-22 14:34:45.273591",
+ "modified_by": "Administrator",
+ "module": "HR",
+ "name": "Department Wise Openings",
+ "number_of_groups": 0,
+ "owner": "Administrator",
+ "time_interval": "Monthly",
+ "timeseries": 0,
+ "timespan": "Last Year",
+ "type": "Bar",
+ "use_report_chart": 0,
+ "y_axis": []
+}
\ No newline at end of file
diff --git a/erpnext/hr/dashboard_chart/designation_wise_employee_count/designation_wise_employee_count.json b/erpnext/hr/dashboard_chart/designation_wise_employee_count/designation_wise_employee_count.json
new file mode 100644
index 0000000..b10235c
--- /dev/null
+++ b/erpnext/hr/dashboard_chart/designation_wise_employee_count/designation_wise_employee_count.json
@@ -0,0 +1,29 @@
+{
+ "chart_name": "Designation Wise Employee Count",
+ "chart_type": "Group By",
+ "creation": "2020-07-22 11:56:32.790337",
+ "custom_options": "",
+ "docstatus": 0,
+ "doctype": "Dashboard Chart",
+ "document_type": "Employee",
+ "dynamic_filters_json": "[[\"Employee\",\"company\",\"=\",\"frappe.defaults.get_user_default(\\\"Company\\\")\"]]",
+ "filters_json": "[[\"Employee\",\"status\",\"=\",\"Active\",false]]",
+ "group_by_based_on": "designation",
+ "group_by_type": "Count",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "last_synced_on": "2020-07-22 14:27:40.602783",
+ "modified": "2020-07-22 14:31:49.665555",
+ "modified_by": "Administrator",
+ "module": "HR",
+ "name": "Designation Wise Employee Count",
+ "number_of_groups": 0,
+ "owner": "Administrator",
+ "time_interval": "Yearly",
+ "timeseries": 0,
+ "timespan": "Last Year",
+ "type": "Donut",
+ "use_report_chart": 0,
+ "y_axis": []
+}
\ No newline at end of file
diff --git a/erpnext/hr/dashboard_chart/designation_wise_openings/designation_wise_openings.json b/erpnext/hr/dashboard_chart/designation_wise_openings/designation_wise_openings.json
new file mode 100644
index 0000000..49ea98a
--- /dev/null
+++ b/erpnext/hr/dashboard_chart/designation_wise_openings/designation_wise_openings.json
@@ -0,0 +1,30 @@
+{
+ "aggregate_function_based_on": "planned_vacancies",
+ "chart_name": "Designation Wise Openings",
+ "chart_type": "Group By",
+ "creation": "2020-07-22 11:56:32.820217",
+ "custom_options": "",
+ "docstatus": 0,
+ "doctype": "Dashboard Chart",
+ "document_type": "Job Opening",
+ "dynamic_filters_json": "",
+ "filters_json": "[]",
+ "group_by_based_on": "designation",
+ "group_by_type": "Sum",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "last_synced_on": "2020-07-22 14:33:44.806626",
+ "modified": "2020-07-22 14:34:32.711881",
+ "modified_by": "Administrator",
+ "module": "HR",
+ "name": "Designation Wise Openings",
+ "number_of_groups": 0,
+ "owner": "Administrator",
+ "time_interval": "Monthly",
+ "timeseries": 0,
+ "timespan": "Last Year",
+ "type": "Bar",
+ "use_report_chart": 0,
+ "y_axis": []
+}
\ No newline at end of file
diff --git a/erpnext/hr/dashboard_chart/gender_diversity_ratio/gender_diversity_ratio.json b/erpnext/hr/dashboard_chart/gender_diversity_ratio/gender_diversity_ratio.json
new file mode 100644
index 0000000..48578c9
--- /dev/null
+++ b/erpnext/hr/dashboard_chart/gender_diversity_ratio/gender_diversity_ratio.json
@@ -0,0 +1,29 @@
+{
+ "chart_name": "Gender Diversity Ratio",
+ "chart_type": "Group By",
+ "creation": "2020-07-22 11:56:32.667291",
+ "custom_options": "",
+ "docstatus": 0,
+ "doctype": "Dashboard Chart",
+ "document_type": "Employee",
+ "dynamic_filters_json": "[[\"Employee\",\"company\",\"=\",\"frappe.defaults.get_user_default(\\\"Company\\\")\"]]",
+ "filters_json": "[[\"Employee\",\"status\",\"=\",\"Active\",false]]",
+ "group_by_based_on": "gender",
+ "group_by_type": "Count",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "last_synced_on": "2020-07-22 14:27:40.143783",
+ "modified": "2020-07-22 14:32:50.962459",
+ "modified_by": "Administrator",
+ "module": "HR",
+ "name": "Gender Diversity Ratio",
+ "number_of_groups": 0,
+ "owner": "Administrator",
+ "time_interval": "Yearly",
+ "timeseries": 0,
+ "timespan": "Last Year",
+ "type": "Pie",
+ "use_report_chart": 0,
+ "y_axis": []
+}
\ No newline at end of file
diff --git a/erpnext/hr/dashboard_chart/job_application_status/job_application_status.json b/erpnext/hr/dashboard_chart/job_application_status/job_application_status.json
new file mode 100644
index 0000000..bfcfa96
--- /dev/null
+++ b/erpnext/hr/dashboard_chart/job_application_status/job_application_status.json
@@ -0,0 +1,29 @@
+{
+ "chart_name": "Job Application Status",
+ "chart_type": "Group By",
+ "creation": "2020-07-22 11:56:32.699696",
+ "custom_options": "",
+ "docstatus": 0,
+ "doctype": "Dashboard Chart",
+ "document_type": "Job Applicant",
+ "dynamic_filters_json": "",
+ "filters_json": "[[\"Job Applicant\",\"creation\",\"Previous\",\"1 month\"]]",
+ "group_by_based_on": "status",
+ "group_by_type": "Count",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "last_synced_on": "2020-07-22 14:27:40.118498",
+ "modified": "2020-07-22 14:33:00.404144",
+ "modified_by": "Administrator",
+ "module": "HR",
+ "name": "Job Application Status",
+ "number_of_groups": 0,
+ "owner": "Administrator",
+ "time_interval": "Yearly",
+ "timeseries": 0,
+ "timespan": "Last Year",
+ "type": "Pie",
+ "use_report_chart": 0,
+ "y_axis": []
+}
\ No newline at end of file
diff --git a/erpnext/hr/dashboard_fixtures.py b/erpnext/hr/dashboard_fixtures.py
deleted file mode 100644
index 6d8091b..0000000
--- a/erpnext/hr/dashboard_fixtures.py
+++ /dev/null
@@ -1,190 +0,0 @@
-# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-import frappe
-import erpnext
-import json
-from frappe import _
-
-def get_data():
-	return frappe._dict({
-		"dashboards": get_dashboards(),
-		"charts": get_charts(),
-		"number_cards": get_number_cards(),
-	})
-
-def get_dashboards():
-	dashboards = []
-	dashboards.append(get_human_resource_dashboard())
-	return dashboards
-
-def get_human_resource_dashboard():
-	return {
-		"name": "Human Resource",
-		"dashboard_name": "Human Resource",
-		"is_default": 1,
-		"charts": [
-			{ "chart": "Attendance Count", "width": "Full"},
-			{ "chart": "Gender Diversity Ratio", "width": "Half"},
-			{ "chart": "Job Application Status", "width": "Half"},
-			{ "chart": 'Designation Wise Employee Count', "width": "Half"},
-			{ "chart": 'Department Wise Employee Count', "width": "Half"},
-			{ "chart": 'Designation Wise Openings', "width": "Half"},
-			{ "chart": 'Department Wise Openings', "width": "Half"}
-		],
-		"cards": [
-			{"card": "Total Employees"},
-			{"card": "New Joinees (Last year)"},
-			{'card': "Employees Left (Last year)"},
-			{'card': "Total Applicants (Last month)"},
-		]
-	}
-
-def get_recruitment_dashboard():
-	pass
-
-
-def get_charts():
-	company = erpnext.get_default_company()
-	date = frappe.utils.get_datetime()
-
-	month_map = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov","Dec"]
-
-
-	if not company:
-		company = frappe.db.get_value("Company", {"is_group": 0}, "name")
-
-	dashboard_charts = [
-		get_dashboards_chart_doc('Gender Diversity Ratio', "Group By", "Pie",
-			document_type = "Employee", group_by_type="Count", group_by_based_on="gender",
-			filters_json = json.dumps([["Employee", "status", "=", "Active"]]))
-	]
-
-	dashboard_charts.append(
-		get_dashboards_chart_doc('Job Application Status', "Group By", "Pie",
-			document_type = "Job Applicant", group_by_type="Count", group_by_based_on="status",
-			filters_json = json.dumps([["Job Applicant", "creation", "Previous", "1 month"]]))
-	)
-
-	custom_options = '''{
-		"type": "line",
-		"axisOptions": {
-			"shortenYAxisNumbers": 1
-		},
-		"tooltipOptions": {}
-	}'''
-
-	filters_json = json.dumps({
-		"month": month_map[date.month - 1],
-		"year": str(date.year),
-		"company":company
-	})
-
-	dashboard_charts.append(
-		get_dashboards_chart_doc('Attendance Count', "Report", "Line",
-			report_name = "Monthly Attendance Sheet", is_custom =1, group_by_type="Count",
-			filters_json = filters_json, custom_options=custom_options)
-	)
-
-	dashboard_charts.append(
-		get_dashboards_chart_doc('Department Wise Employee Count', "Group By", "Donut",
-			document_type = "Employee", group_by_type="Count", group_by_based_on="department",
-			filters_json = json.dumps([["Employee", "status", "=", "Active"]]))
-	)
-
-	dashboard_charts.append(
-		get_dashboards_chart_doc('Designation Wise Employee Count', "Group By", "Donut",
-			document_type = "Employee", group_by_type="Count", group_by_based_on="designation",
-			filters_json = json.dumps([["Employee", "status", "=", "Active"]]))
-	)
-
-	dashboard_charts.append(
-		get_dashboards_chart_doc('Designation Wise Openings', "Group By", "Bar",
-			document_type = "Job Opening", group_by_type="Sum", group_by_based_on="designation",
-			time_interval = "Monthly", aggregate_function_based_on = "planned_vacancies")
-	)
-	dashboard_charts.append(
-		get_dashboards_chart_doc('Department Wise Openings', "Group By", "Bar",
-			document_type = "Job Opening", group_by_type="Sum", group_by_based_on="department",
-			time_interval = "Monthly", aggregate_function_based_on = "planned_vacancies")
-	)
-	return dashboard_charts
-
-
-def get_number_cards():
-	number_cards = []
-
-	number_cards = [
-		get_number_cards_doc("Employee", "Total Employees", filters_json = json.dumps([
-				["Employee","status","=","Active"]
-			])
-		)
-	]
-
-	number_cards.append(
-		get_number_cards_doc("Employee", "New Joinees (Last year)", filters_json = json.dumps([
-				["Employee","date_of_joining","Previous","1 year"],
-				["Employee","status","=","Active"]
-			])
-		)
-	)
-
-	number_cards.append(
-		get_number_cards_doc("Employee", "Employees Left (Last year)", filters_json = json.dumps([
-				["Employee", "relieving_date", "Previous", "1 year"],
-				["Employee", "status", "=", "Left"]
-			])
-		)
-	)
-
-	number_cards.append(
-		get_number_cards_doc("Job Applicant", "Total Applicants (Last month)", filters_json = json.dumps([
-				["Job Applicant", "creation", "Previous", "1 month"]
-			])
-		)
-	)
-
-	return number_cards
-
-
-def get_number_cards_doc(document_type, label, **args):
-	args = frappe._dict(args)
-
-	return {
-			"doctype": "Number Card",
-			"document_type": document_type,
-			"function": args.func or "Count",
-			"is_public": args.is_public or 1,
-			"label": _(label),
-			"name": args.name or label,
-			"show_percentage_stats": args.show_percentage_stats or 1,
-			"stats_time_interval": args.stats_time_interval or 'Monthly',
-			"filters_json": args.filters_json or '[]',
-			"aggregate_function_based_on": args.aggregate_function_based_on or None
-		}
-
-def get_dashboards_chart_doc(name, chart_type, graph_type, **args):
-	args = frappe._dict(args)
-
-	return {
-			"name": name,
-			"chart_name": _(args.chart_name or name),
-			"chart_type": chart_type,
-			"document_type": args.document_type or None,
-			"report_name": args.report_name or None,
-			"is_custom": args.is_custom or 0,
-			"group_by_type": args.group_by_type or None,
-			"group_by_based_on": args.group_by_based_on or None,
-			"based_on": args.based_on or None,
-			"value_based_on": args.value_based_on or None,
-			"number_of_groups": args.number_of_groups or 0,
-			"is_public": args.is_public or 1,
-			"timespan": args.timespan or "Last Year",
-			"time_interval": args.time_interval or "Yearly",
-			"timeseries": args.timeseries or 0,
-			"filters_json": args.filters_json or '[]',
-			"type": graph_type,
-			"custom_options": args.custom_options or '',
-			"doctype": "Dashboard Chart",
-			"aggregate_function_based_on": args.aggregate_function_based_on or None
-		}
\ No newline at end of file
diff --git a/erpnext/hr/doctype/employee/employee.json b/erpnext/hr/doctype/employee/employee.json
index 7dacacf1..f2afe06 100644
--- a/erpnext/hr/doctype/employee/employee.json
+++ b/erpnext/hr/doctype/employee/employee.json
@@ -410,6 +410,8 @@
    "options": "Branch"
   },
   {
+   "fetch_from": "grade.default_leave_policy",
+   "fetch_if_empty": 1,
    "fieldname": "leave_policy",
    "fieldtype": "Link",
    "label": "Leave Policy",
@@ -804,16 +806,14 @@
    "fieldname": "expense_approver",
    "fieldtype": "Link",
    "label": "Expense Approver",
-   "options": "User",
-   "show_days": 1,
-   "show_seconds": 1
+   "options": "User"
   }
  ],
  "icon": "fa fa-user",
  "idx": 24,
  "image_field": "image",
  "links": [],
- "modified": "2020-06-18 18:01:27.223535",
+ "modified": "2020-07-03 21:28:04.109189",
  "modified_by": "Administrator",
  "module": "HR",
  "name": "Employee",
diff --git a/erpnext/hr/doctype/employee/employee.py b/erpnext/hr/doctype/employee/employee.py
index 4d49503..7338cbb 100755
--- a/erpnext/hr/doctype/employee/employee.py
+++ b/erpnext/hr/doctype/employee/employee.py
@@ -413,7 +413,11 @@
 
 @frappe.whitelist()
 def get_children(doctype, parent=None, company=None, is_root=False, is_tree=False):
-	filters = [['company', '=', company]]
+
+	filters = []
+	if company and company != 'All Companies':
+		filters = [['company', '=', company]]
+
 	fields = ['name as value', 'employee_name as title']
 
 	if is_root:
diff --git a/erpnext/hr/doctype/employee/employee_tree.js b/erpnext/hr/doctype/employee/employee_tree.js
index 0a2da63..9ab091a 100644
--- a/erpnext/hr/doctype/employee/employee_tree.js
+++ b/erpnext/hr/doctype/employee/employee_tree.js
@@ -4,7 +4,7 @@
 		{
 			fieldname: "company",
 			fieldtype:"Select",
-			options: erpnext.utils.get_tree_options("company"),
+			options: ['All Companies'].concat(erpnext.utils.get_tree_options("company")),
 			label: __("Company"),
 			default: erpnext.utils.get_tree_default("company")
 		}
diff --git a/erpnext/hr/doctype/employee_advance/employee_advance.py b/erpnext/hr/doctype/employee_advance/employee_advance.py
index 7619581..3c435b8 100644
--- a/erpnext/hr/doctype/employee_advance/employee_advance.py
+++ b/erpnext/hr/doctype/employee_advance/employee_advance.py
@@ -120,12 +120,14 @@
 		"reference_type": "Employee Advance",
 		"reference_name": doc.name,
 		"party_type": "Employee",
+		"cost_center": erpnext.get_default_cost_center(doc.company),
 		"party": doc.employee,
 		"is_advance": "Yes"
 	})
 
 	je.append("accounts", {
 		"account": payment_account.account,
+		"cost_center": erpnext.get_default_cost_center(doc.company),
 		"credit_in_account_currency": flt(doc.advance_amount),
 		"account_currency": payment_account.account_currency,
 		"account_type": payment_account.account_type
diff --git a/erpnext/hr/doctype/employee_checkin/employee_checkin.json b/erpnext/hr/doctype/employee_checkin/employee_checkin.json
index 75f6997..d34316d 100644
--- a/erpnext/hr/doctype/employee_checkin/employee_checkin.json
+++ b/erpnext/hr/doctype/employee_checkin/employee_checkin.json
@@ -41,8 +41,7 @@
    "fieldtype": "Select",
    "in_list_view": 1,
    "label": "Log Type",
-   "options": "\nIN\nOUT",
-   "reqd": 1
+   "options": "\nIN\nOUT"
   },
   {
    "fieldname": "shift",
@@ -108,7 +107,7 @@
   }
  ],
  "links": [],
- "modified": "2020-01-23 04:57:42.551355",
+ "modified": "2020-07-08 11:02:32.660986",
  "modified_by": "Administrator",
  "module": "HR",
  "name": "Employee Checkin",
diff --git a/erpnext/hr/doctype/employee_onboarding/employee_onboarding.js b/erpnext/hr/doctype/employee_onboarding/employee_onboarding.js
index c128567..d6047e1 100644
--- a/erpnext/hr/doctype/employee_onboarding/employee_onboarding.js
+++ b/erpnext/hr/doctype/employee_onboarding/employee_onboarding.js
@@ -8,10 +8,20 @@
 		frm.add_fetch("employee_onboarding_template", "designation", "designation");
 		frm.add_fetch("employee_onboarding_template", "employee_grade", "employee_grade");
 
+
+		frm.set_query("job_applicant", function () {
+			return {
+				filters:{
+					"status": "Accepted",
+				}
+			};
+		});
+
 		frm.set_query('job_offer', function () {
 			return {
 				filters: {
-					'job_applicant': frm.doc.job_applicant
+					'job_applicant': frm.doc.job_applicant,
+					'docstatus': 1
 				}
 			};
 		});
diff --git a/erpnext/hr/doctype/employee_onboarding/employee_onboarding.json b/erpnext/hr/doctype/employee_onboarding/employee_onboarding.json
index 3b95cab..783c757 100644
--- a/erpnext/hr/doctype/employee_onboarding/employee_onboarding.json
+++ b/erpnext/hr/doctype/employee_onboarding/employee_onboarding.json
@@ -1,620 +1,203 @@
 {
- "allow_copy": 0, 
- "allow_guest_to_view": 0, 
- "allow_import": 0, 
- "allow_rename": 0, 
- "autoname": "HR-EMP-ONB-.YYYY.-.#####", 
- "beta": 0, 
- "creation": "2018-05-09 04:57:20.016220", 
- "custom": 0, 
- "docstatus": 0, 
- "doctype": "DocType", 
- "document_type": "", 
- "editable_grid": 1, 
- "engine": "InnoDB", 
+ "actions": [],
+ "autoname": "HR-EMP-ONB-.YYYY.-.#####",
+ "creation": "2018-05-09 04:57:20.016220",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "job_applicant",
+  "job_offer",
+  "employee_name",
+  "employee",
+  "date_of_joining",
+  "boarding_status",
+  "notify_users_by_email",
+  "column_break_7",
+  "employee_onboarding_template",
+  "company",
+  "department",
+  "designation",
+  "employee_grade",
+  "project",
+  "table_for_activity",
+  "activities",
+  "amended_from"
+ ],
  "fields": [
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "job_applicant", 
-   "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": "Job Applicant", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Job Applicant", 
-   "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
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "job_offer", 
-   "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": "Job Offer", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Job Offer", 
-   "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_from": "job_applicant.applicant_name", 
-   "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": 1, 
-   "in_standard_filter": 0, 
-   "label": "Employee Name", 
-   "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
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 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": 0, 
-   "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": 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, 
-   "fieldname": "date_of_joining", 
-   "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": "Date of Joining", 
-   "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": 1, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "boarding_status", 
-   "fieldtype": "Select", 
-   "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": "Status", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "\nPending\nIn Process\nCompleted", 
-   "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": "job_applicant",
+   "fieldtype": "Link",
+   "label": "Job Applicant",
+   "options": "Job Applicant",
+   "reqd": 1,
+   "show_days": 1,
+   "show_seconds": 1
   },
   {
-    "allow_bulk_edit": 0,
-    "allow_in_quick_entry": 0,
-    "allow_on_submit": 1,
-    "bold": 0,
-    "collapsible": 0,
-    "columns": 0,
-    "fieldname": "notify_users_by_email",
-    "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": "Notify users by email",
-    "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": "job_offer",
+   "fieldtype": "Link",
+   "label": "Job Offer",
+   "options": "Job Offer",
+   "reqd": 1,
+   "show_days": 1,
+   "show_seconds": 1
+  },
   {
-   "allow_bulk_edit": 0,
-   "allow_in_quick_entry": 0,
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "column_break_7", 
-   "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
-  }, 
+   "fetch_from": "job_applicant.applicant_name",
+   "fieldname": "employee_name",
+   "fieldtype": "Data",
+   "in_list_view": 1,
+   "label": "Employee Name",
+   "reqd": 1,
+   "show_days": 1,
+   "show_seconds": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "employee_onboarding_template", 
-   "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": "Employee Onboarding Template", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Employee Onboarding Template", 
-   "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": "employee",
+   "fieldtype": "Link",
+   "label": "Employee",
+   "options": "Employee",
+   "read_only": 1,
+   "show_days": 1,
+   "show_seconds": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "company", 
-   "fieldtype": "Link", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_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
-  }, 
+   "fieldname": "date_of_joining",
+   "fieldtype": "Date",
+   "in_list_view": 1,
+   "label": "Date of Joining",
+   "show_days": 1,
+   "show_seconds": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 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": 1, 
-   "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": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "allow_on_submit": 1,
+   "fieldname": "boarding_status",
+   "fieldtype": "Select",
+   "label": "Status",
+   "options": "\nPending\nIn Process\nCompleted",
+   "show_days": 1,
+   "show_seconds": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "designation", 
-   "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": "Designation", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Designation", 
-   "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_on_submit": 1,
+   "default": "0",
+   "fieldname": "notify_users_by_email",
+   "fieldtype": "Check",
+   "label": "Notify users by email",
+   "show_days": 1,
+   "show_seconds": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "employee_grade", 
-   "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": "Employee Grade", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Employee Grade", 
-   "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_7",
+   "fieldtype": "Column Break",
+   "show_days": 1,
+   "show_seconds": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "project", 
-   "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": "Project", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Project", 
-   "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": "employee_onboarding_template",
+   "fieldtype": "Link",
+   "label": "Employee Onboarding Template",
+   "options": "Employee Onboarding Template",
+   "show_days": 1,
+   "show_seconds": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "table_for_activity", 
-   "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": "", 
-   "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": "company",
+   "fieldtype": "Link",
+   "label": "Company",
+   "options": "Company",
+   "show_days": 1,
+   "show_seconds": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 1, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "activities", 
-   "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": "Activities", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Employee Boarding Activity", 
-   "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": "department",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "label": "Department",
+   "options": "Department",
+   "show_days": 1,
+   "show_seconds": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 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 Onboarding", 
-   "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": "designation",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "label": "Designation",
+   "options": "Designation",
+   "show_days": 1,
+   "show_seconds": 1
+  },
+  {
+   "fieldname": "employee_grade",
+   "fieldtype": "Link",
+   "label": "Employee Grade",
+   "options": "Employee Grade",
+   "show_days": 1,
+   "show_seconds": 1
+  },
+  {
+   "fieldname": "project",
+   "fieldtype": "Link",
+   "label": "Project",
+   "options": "Project",
+   "read_only": 1,
+   "show_days": 1,
+   "show_seconds": 1
+  },
+  {
+   "fieldname": "table_for_activity",
+   "fieldtype": "Section Break",
+   "show_days": 1,
+   "show_seconds": 1
+  },
+  {
+   "allow_on_submit": 1,
+   "fieldname": "activities",
+   "fieldtype": "Table",
+   "label": "Activities",
+   "options": "Employee Boarding Activity",
+   "show_days": 1,
+   "show_seconds": 1
+  },
+  {
+   "fieldname": "amended_from",
+   "fieldtype": "Link",
+   "label": "Amended From",
+   "no_copy": 1,
+   "options": "Employee Onboarding",
+   "print_hide": 1,
+   "read_only": 1,
+   "show_days": 1,
+   "show_seconds": 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-08-01 16:15:55.968224", 
- "modified_by": "Administrator", 
- "module": "HR", 
- "name": "Employee Onboarding", 
- "name_case": "", 
- "owner": "Administrator", 
+ ],
+ "is_submittable": 1,
+ "links": [],
+ "modified": "2020-06-25 15:22:24.923835",
+ "modified_by": "Administrator",
+ "module": "HR",
+ "name": "Employee Onboarding",
+ "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
   }
- ], 
- "quick_entry": 0, 
- "read_only": 0, 
- "read_only_onload": 0, 
- "show_name_in_global_search": 0, 
- "sort_field": "modified", 
- "sort_order": "DESC", 
- "title_field": "employee_name", 
- "track_changes": 1, 
- "track_seen": 0, 
- "track_views": 0
+ ],
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "title_field": "employee_name",
+ "track_changes": 1
 }
\ No newline at end of file
diff --git a/erpnext/hr/doctype/employee_onboarding/employee_onboarding.py b/erpnext/hr/doctype/employee_onboarding/employee_onboarding.py
index 19ff3bd..6cc2bf5 100644
--- a/erpnext/hr/doctype/employee_onboarding/employee_onboarding.py
+++ b/erpnext/hr/doctype/employee_onboarding/employee_onboarding.py
@@ -13,6 +13,12 @@
 class EmployeeOnboarding(EmployeeBoardingController):
 	def validate(self):
 		super(EmployeeOnboarding, self).validate()
+		self.validate_duplicate_employee_onboarding()
+
+	def validate_duplicate_employee_onboarding(self):
+		emp_onboarding = frappe.db.exists("Employee Onboarding",{"job_applicant": self.job_applicant})
+		if emp_onboarding and emp_onboarding != self.name:
+			frappe.throw(_("Employee Onboarding: {0} is already for Job Applicant: {1}").format(frappe.bold(emp_onboarding), frappe.bold(self.job_applicant)))
 
 	def validate_employee_creation(self):
 		if self.docstatus != 1:
diff --git a/erpnext/hr/doctype/employee_onboarding/test_employee_onboarding.py b/erpnext/hr/doctype/employee_onboarding/test_employee_onboarding.py
index 35c9f72..4e9ee3b 100644
--- a/erpnext/hr/doctype/employee_onboarding/test_employee_onboarding.py
+++ b/erpnext/hr/doctype/employee_onboarding/test_employee_onboarding.py
@@ -8,6 +8,7 @@
 from frappe.utils import nowdate
 from erpnext.hr.doctype.employee_onboarding.employee_onboarding import make_employee
 from erpnext.hr.doctype.employee_onboarding.employee_onboarding import IncompleteTaskError
+from erpnext.hr.doctype.job_offer.test_job_offer import create_job_offer
 
 class TestEmployeeOnboarding(unittest.TestCase):
 	def test_employee_onboarding_incomplete_task(self):
@@ -15,8 +16,13 @@
 			frappe.delete_doc('Employee Onboarding', {'employee_name': 'Test Researcher'})
 		_set_up()
 		applicant = get_job_applicant()
+
+		job_offer = create_job_offer(job_applicant=applicant.name)
+		job_offer.submit()
+
 		onboarding = frappe.new_doc('Employee Onboarding')
 		onboarding.job_applicant = applicant.name
+		onboarding.job_offer = job_offer.name
 		onboarding.company = '_Test Company'
 		onboarding.designation = 'Researcher'
 		onboarding.append('activities', {
diff --git a/erpnext/hr/doctype/expense_claim/expense_claim.js b/erpnext/hr/doctype/expense_claim/expense_claim.js
index 6bb9af9..221300b 100644
--- a/erpnext/hr/doctype/expense_claim/expense_claim.js
+++ b/erpnext/hr/doctype/expense_claim/expense_claim.js
@@ -113,6 +113,14 @@
 	cur_frm.cscript.calculate_total(doc,cdt,cdn);
 };
 
+cur_frm.fields_dict['cost_center'].get_query = function(doc) {
+	return {
+		filters: {
+			"company": doc.company
+		}
+	}
+};
+
 erpnext.expense_claim = {
 	set_title: function(frm) {
 		if (!frm.doc.task) {
@@ -213,12 +221,15 @@
 	refresh: function(frm) {
 		frm.trigger("toggle_fields");
 
-		if(frm.doc.docstatus === 1 && frm.doc.approval_status !== "Rejected") {
+		if(frm.doc.docstatus > 0 && frm.doc.approval_status !== "Rejected") {
 			frm.add_custom_button(__('Accounting Ledger'), function() {
 				frappe.route_options = {
 					voucher_no: frm.doc.name,
 					company: frm.doc.company,
-					group_by_voucher: false
+					from_date: frm.doc.posting_date,
+					to_date: moment(frm.doc.modified).format('YYYY-MM-DD'),
+					group_by: '',
+					show_cancelled_entries: frm.doc.docstatus === 2
 				};
 				frappe.set_route("query-report", "General Ledger");
 			}, __("View"));
@@ -297,6 +308,11 @@
 	cost_center: function(frm) {
 		frm.events.set_child_cost_center(frm);
 	},
+
+	validate: function(frm) {
+		frm.events.set_child_cost_center(frm);
+	},
+
 	set_child_cost_center: function(frm){
 		(frm.doc.expenses || []).forEach(function(d) {
 			if (!d.cost_center){
@@ -346,9 +362,6 @@
 });
 
 frappe.ui.form.on("Expense Claim Detail", {
-	expenses_add: function(frm, cdt, cdn) {
-		frm.events.set_child_cost_center(frm);
-	},
 	amount: function(frm, cdt, cdn) {
 		var child = locals[cdt][cdn];
 		frappe.model.set_value(cdt, cdn, 'sanctioned_amount', child.amount);
diff --git a/erpnext/hr/doctype/expense_claim/expense_claim.py b/erpnext/hr/doctype/expense_claim/expense_claim.py
index ea469b8..bf893d5 100644
--- a/erpnext/hr/doctype/expense_claim/expense_claim.py
+++ b/erpnext/hr/doctype/expense_claim/expense_claim.py
@@ -129,7 +129,7 @@
 					"debit": data.sanctioned_amount,
 					"debit_in_account_currency": data.sanctioned_amount,
 					"against": self.employee,
-					"cost_center": data.cost_center
+					"cost_center": data.cost_center or self.cost_center
 				}, item=data)
 			)
 
@@ -295,7 +295,7 @@
 	je = frappe.new_doc("Journal Entry")
 	je.voucher_type = 'Bank Entry'
 	je.company = expense_claim.company
-	je.remark = 'Payment against Expense Claim: ' + dn;
+	je.remark = 'Payment against Expense Claim: ' + dn
 
 	je.append("accounts", {
 		"account": expense_claim.payable_account,
@@ -303,6 +303,7 @@
 		"reference_type": "Expense Claim",
 		"party_type": "Employee",
 		"party": expense_claim.employee,
+		"cost_center": erpnext.get_default_cost_center(expense_claim.company),
 		"reference_name": expense_claim.name
 	})
 
@@ -313,6 +314,7 @@
 		"reference_name": expense_claim.name,
 		"balance": default_bank_cash_account.balance,
 		"account_currency": default_bank_cash_account.account_currency,
+		"cost_center": erpnext.get_default_cost_center(expense_claim.company),
 		"account_type": default_bank_cash_account.account_type
 	})
 
diff --git a/erpnext/hr/doctype/job_applicant/job_applicant.js b/erpnext/hr/doctype/job_applicant/job_applicant.js
index 05071e1..c625155 100644
--- a/erpnext/hr/doctype/job_applicant/job_applicant.js
+++ b/erpnext/hr/doctype/job_applicant/job_applicant.js
@@ -10,10 +10,14 @@
 	refresh: function(frm) {
 		if (!frm.doc.__islocal) {
 			if (frm.doc.__onload && frm.doc.__onload.job_offer) {
+				$('[data-doctype="Employee Onboarding"]').find("button").show();
+				$('[data-doctype="Job Offer"]').find("button").hide();
 				frm.add_custom_button(__("Job Offer"), function() {
 					frappe.set_route("Form", "Job Offer", frm.doc.__onload.job_offer);
 				}, __("View"));
 			} else {
+				$('[data-doctype="Employee Onboarding"]').find("button").hide();
+				$('[data-doctype="Job Offer"]').find("button").show();
 				frm.add_custom_button(__("Job Offer"), function() {
 					frappe.route_options = {
 						"job_applicant": frm.doc.name,
diff --git a/erpnext/hr/doctype/job_applicant/job_applicant_list.js b/erpnext/hr/doctype/job_applicant/job_applicant_list.js
new file mode 100644
index 0000000..3b9141b
--- /dev/null
+++ b/erpnext/hr/doctype/job_applicant/job_applicant_list.js
@@ -0,0 +1,15 @@
+// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
+// MIT License. See license.txt
+
+frappe.listview_settings['Job Applicant'] = {
+	add_fields: ["company", "designation", "job_applicant", "status"],
+	get_indicator: function (doc) {
+		if (doc.status == "Accepted") {
+			return [__(doc.status), "green", "status,=," + doc.status];
+		} else if (["Open", "Replied"].includes(doc.status)) {
+			return [__(doc.status), "orange", "status,=," + doc.status];
+		} else if (["Hold", "Rejected"].includes(doc.status)) {
+			return [__(doc.status), "red", "status,=," + doc.status];
+		}
+	}
+};
diff --git a/erpnext/hr/doctype/job_offer/job_offer.json b/erpnext/hr/doctype/job_offer/job_offer.json
index ccbfdc5..c0b7f69 100644
--- a/erpnext/hr/doctype/job_offer/job_offer.json
+++ b/erpnext/hr/doctype/job_offer/job_offer.json
@@ -30,7 +30,6 @@
   {
    "fieldname": "job_applicant",
    "fieldtype": "Link",
-   "in_list_view": 1,
    "label": "Job Applicant",
    "options": "Job Applicant",
    "print_hide": 1,
@@ -161,7 +160,7 @@
  ],
  "is_submittable": 1,
  "links": [],
- "modified": "2019-12-31 02:40:33.650728",
+ "modified": "2020-06-25 00:56:24.756395",
  "modified_by": "Administrator",
  "module": "HR",
  "name": "Job Offer",
diff --git a/erpnext/hr/doctype/job_offer/job_offer.py b/erpnext/hr/doctype/job_offer/job_offer.py
index 32f1b89..e7e1a37 100644
--- a/erpnext/hr/doctype/job_offer/job_offer.py
+++ b/erpnext/hr/doctype/job_offer/job_offer.py
@@ -15,15 +15,17 @@
 
 	def validate(self):
 		self.validate_vacancies()
+		job_offer = frappe.db.exists("Job Offer",{"job_applicant": self.job_applicant})
+		if job_offer and job_offer != self.name:
+			frappe.throw(_("Job Offer: {0} is already for Job Applicant: {1}").format(frappe.bold(job_offer), frappe.bold(self.job_applicant)))
 
 	def validate_vacancies(self):
 		staffing_plan = get_staffing_plan_detail(self.designation, self.company, self.offer_date)
 		check_vacancies = frappe.get_single("HR Settings").check_vacancies
 		if staffing_plan and check_vacancies:
-			vacancies = frappe.db.get_value("Staffing Plan Detail", filters={"name": staffing_plan.name}, fieldname=['vacancies'])
-			job_offers = len(self.get_job_offer(staffing_plan.from_date, staffing_plan.to_date))
-			if vacancies - job_offers <= 0:
-				frappe.throw(_("There are no vacancies under staffing plan {0}").format(get_link_to_form("Staffing Plan", staffing_plan.parent)))
+			job_offers = self.get_job_offer(staffing_plan.from_date, staffing_plan.to_date)
+			if staffing_plan.vacancies - len(job_offers) <= 0:
+				frappe.throw(_("There are no vacancies under staffing plan {0}").format(frappe.bold(get_link_to_form("Staffing Plan", staffing_plan.parent))))
 
 	def on_change(self):
 		update_job_applicant(self.status, self.job_applicant)
@@ -33,7 +35,8 @@
 		return frappe.get_all("Job Offer", filters={
 				"offer_date": ['between', (from_date, to_date)],
 				"designation": self.designation,
-				"company": self.company
+				"company": self.company,
+				"docstatus": 1
 			}, fields=['name'])
 
 def update_job_applicant(status, job_applicant):
@@ -42,18 +45,22 @@
 
 def get_staffing_plan_detail(designation, company, offer_date):
 	detail = frappe.db.sql("""
-		SELECT spd.name as name,
+		SELECT DISTINCT spd.parent,
 			sp.from_date as from_date,
 			sp.to_date as to_date,
-			sp.name as parent
+			sp.name,
+			sum(spd.vacancies) as vacancies,
+			spd.designation
 		FROM `tabStaffing Plan Detail` spd, `tabStaffing Plan` sp
 		WHERE
 			sp.docstatus=1
 			AND spd.designation=%s
 			AND sp.company=%s
+			AND spd.parent = sp.name
 			AND %s between sp.from_date and sp.to_date
 	""", (designation, company, offer_date), as_dict=1)
-	return detail[0] if detail else None
+
+	return frappe._dict(detail[0]) if detail else None
 
 @frappe.whitelist()
 def make_employee(source_name, target_doc=None):
diff --git a/erpnext/hr/doctype/job_offer/job_offer_list.js b/erpnext/hr/doctype/job_offer/job_offer_list.js
new file mode 100644
index 0000000..4fa5be7
--- /dev/null
+++ b/erpnext/hr/doctype/job_offer/job_offer_list.js
@@ -0,0 +1,15 @@
+// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
+// MIT License. See license.txt
+
+frappe.listview_settings['Job Offer'] = {
+	add_fields: ["company", "designation", "job_applicant", "status"],
+	get_indicator: function (doc) {
+		if (doc.status == "Accepted") {
+			return [__(doc.status), "green", "status,=," + doc.status];
+		} else if (doc.status == "Awaiting Response") {
+			return [__(doc.status), "orange", "status,=," + doc.status];
+		} else if (doc.status == "Rejected") {
+			return [__(doc.status), "red", "status,=," + doc.status];
+		}
+	}
+};
diff --git a/erpnext/hr/doctype/leave_application/leave_application.js b/erpnext/hr/doctype/leave_application/leave_application.js
index fb1f2c0..4001a45 100755
--- a/erpnext/hr/doctype/leave_application/leave_application.js
+++ b/erpnext/hr/doctype/leave_application/leave_application.js
@@ -40,6 +40,8 @@
 	validate: function(frm) {
 		if (frm.doc.from_date == frm.doc.to_date && frm.doc.half_day == 1){
 			frm.doc.half_day_date = frm.doc.from_date;
+		}else if (frm.doc.half_day == 0){
+			frm.doc.half_day_date = "";
 		}
 		frm.toggle_reqd("half_day_date", frm.doc.half_day == 1);
 	},
diff --git a/erpnext/hr/doctype/leave_application/leave_application.py b/erpnext/hr/doctype/leave_application/leave_application.py
index 0423824..3f25f58 100755
--- a/erpnext/hr/doctype/leave_application/leave_application.py
+++ b/erpnext/hr/doctype/leave_application/leave_application.py
@@ -293,6 +293,8 @@
 	def set_half_day_date(self):
 		if self.from_date == self.to_date and self.half_day == 1:
 			self.half_day_date = self.from_date
+		elif self.half_day == 0:
+			self.half_day_date = None
 
 	def notify_employee(self):
 		employee = frappe.get_doc("Employee", self.employee)
diff --git a/erpnext/hr/doctype/leave_policy/leave_policy_dashboard.py b/erpnext/hr/doctype/leave_policy/leave_policy_dashboard.py
index 48a2045..ff5dc2f 100644
--- a/erpnext/hr/doctype/leave_policy/leave_policy_dashboard.py
+++ b/erpnext/hr/doctype/leave_policy/leave_policy_dashboard.py
@@ -1,4 +1,5 @@
 from __future__ import unicode_literals
+from frappe import _
 
 def get_data():
 	return {
@@ -8,13 +9,17 @@
 		},
 		'transactions': [
 			{
-				'items': ['Employee']
+				'label': _('Employees'),
+				'items': ['Employee', 'Employee Grade']
 			},
 			{
-				'items': ['Employee Grade']
-			},
-			{
+				'label': _('Leaves'),
 				'items': ['Leave Allocation']
 			},
 		]
-	}
\ No newline at end of file
+	}
+
+
+
+
+	
\ No newline at end of file
diff --git a/erpnext/hr/doctype/vehicle/vehicle.py b/erpnext/hr/doctype/vehicle/vehicle.py
index a75cfa6..1df5068 100644
--- a/erpnext/hr/doctype/vehicle/vehicle.py
+++ b/erpnext/hr/doctype/vehicle/vehicle.py
@@ -13,4 +13,11 @@
 		if getdate(self.start_date) > getdate(self.end_date):
 			frappe.throw(_("Insurance Start date should be less than Insurance End date"))
 		if getdate(self.carbon_check_date) > getdate():
-			frappe.throw(_("Last carbon check date cannot be a future date"))
\ No newline at end of file
+			frappe.throw(_("Last carbon check date cannot be a future date"))
+
+def get_timeline_data(doctype, name):
+	'''Return timeline for vehicle log'''
+	return dict(frappe.db.sql('''select unix_timestamp(date), count(*)
+	from `tabVehicle Log` where license_plate=%s
+	and date > date_sub(curdate(), interval 1 year)
+	group by date''', name))
diff --git a/erpnext/hr/hr_dashboard/human_resource/human_resource.json b/erpnext/hr/hr_dashboard/human_resource/human_resource.json
new file mode 100644
index 0000000..f74d9a3
--- /dev/null
+++ b/erpnext/hr/hr_dashboard/human_resource/human_resource.json
@@ -0,0 +1,58 @@
+{
+ "cards": [
+  {
+   "card": "Total Employees"
+  },
+  {
+   "card": "New Joinees (Last year)"
+  },
+  {
+   "card": "Employees Left (Last year)"
+  },
+  {
+   "card": "Total Applicants (Last month)"
+  }
+ ],
+ "charts": [
+  {
+   "chart": "Attendance Count",
+   "width": "Full"
+  },
+  {
+   "chart": "Gender Diversity Ratio",
+   "width": "Half"
+  },
+  {
+   "chart": "Job Application Status",
+   "width": "Half"
+  },
+  {
+   "chart": "Designation Wise Employee Count",
+   "width": "Half"
+  },
+  {
+   "chart": "Department Wise Employee Count",
+   "width": "Half"
+  },
+  {
+   "chart": "Designation Wise Openings",
+   "width": "Half"
+  },
+  {
+   "chart": "Department Wise Openings",
+   "width": "Half"
+  }
+ ],
+ "creation": "2020-07-22 11:56:33.015888",
+ "dashboard_name": "Human Resource",
+ "docstatus": 0,
+ "doctype": "Dashboard",
+ "idx": 0,
+ "is_default": 0,
+ "is_standard": 1,
+ "modified": "2020-07-22 14:42:12.789249",
+ "modified_by": "Administrator",
+ "module": "HR",
+ "name": "Human Resource",
+ "owner": "Administrator"
+}
\ No newline at end of file
diff --git a/erpnext/hr/module_onboarding/human_resource/human_resource.json b/erpnext/hr/module_onboarding/human_resource/human_resource.json
index e64582b..518c002 100644
--- a/erpnext/hr/module_onboarding/human_resource/human_resource.json
+++ b/erpnext/hr/module_onboarding/human_resource/human_resource.json
@@ -13,7 +13,7 @@
  "documentation_url": "https://docs.erpnext.com/docs/user/manual/en/human-resources",
  "idx": 0,
  "is_complete": 0,
- "modified": "2020-05-20 11:20:07.992597",
+ "modified": "2020-07-08 14:05:47.018799",
  "modified_by": "Administrator",
  "module": "HR",
  "name": "Human Resource",
@@ -44,8 +44,7 @@
    "step": "HR Settings"
   }
  ],
- "subtitle": "Employee, Leaves and more.",
- "success_message": "The HR Module is all set up!",
- "title": "Let's Setup the Human Resource Module. ",
- "user_can_dismiss": 0
+ "subtitle": "Employee, Leaves, and more.",
+ "success_message": "The Human Resource Module is all set up!",
+ "title": "Let's Set Up the Human Resource Module. "
 }
\ No newline at end of file
diff --git "a/erpnext/hr/number_card/employees_left_\050last_year\051/employees_left_\050last_year\051.json" "b/erpnext/hr/number_card/employees_left_\050last_year\051/employees_left_\050last_year\051.json"
new file mode 100644
index 0000000..6a91912
--- /dev/null
+++ "b/erpnext/hr/number_card/employees_left_\050last_year\051/employees_left_\050last_year\051.json"
@@ -0,0 +1,21 @@
+{
+ "creation": "2020-07-22 11:56:32.947790",
+ "docstatus": 0,
+ "doctype": "Number Card",
+ "document_type": "Employee",
+ "dynamic_filters_json": "[[\"Employee\",\"company\",\"=\",\"frappe.defaults.get_user_default(\\\"Company\\\")\"]]",
+ "filters_json": "[[\"Employee\",\"relieving_date\",\"Timespan\",\"last year\",false]]",
+ "function": "Count",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "label": "Employees Left (Last year)",
+ "modified": "2020-07-23 12:03:26.747447",
+ "modified_by": "Administrator",
+ "module": "HR",
+ "name": "Employees Left (Last year)",
+ "owner": "Administrator",
+ "show_percentage_stats": 1,
+ "stats_time_interval": "Monthly",
+ "type": "Document Type"
+}
\ No newline at end of file
diff --git "a/erpnext/hr/number_card/new_joinees_\050last_year\051/new_joinees_\050last_year\051.json" "b/erpnext/hr/number_card/new_joinees_\050last_year\051/new_joinees_\050last_year\051.json"
new file mode 100644
index 0000000..8f5ad9c
--- /dev/null
+++ "b/erpnext/hr/number_card/new_joinees_\050last_year\051/new_joinees_\050last_year\051.json"
@@ -0,0 +1,21 @@
+{
+ "creation": "2020-07-22 11:56:32.914057",
+ "docstatus": 0,
+ "doctype": "Number Card",
+ "document_type": "Employee",
+ "dynamic_filters_json": "[[\"Employee\",\"company\",\"=\",\"frappe.defaults.get_user_default(\\\"Company\\\")\"]]",
+ "filters_json": "[[\"Employee\",\"date_of_joining\",\"Timespan\",\"last year\",false],[\"Employee\",\"status\",\"=\",\"Active\",false]]",
+ "function": "Count",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "label": "New Joinees (Last year)",
+ "modified": "2020-07-22 14:32:09.352301",
+ "modified_by": "Administrator",
+ "module": "HR",
+ "name": "New Joinees (Last year)",
+ "owner": "Administrator",
+ "show_percentage_stats": 1,
+ "stats_time_interval": "Monthly",
+ "type": "Document Type"
+}
\ No newline at end of file
diff --git "a/erpnext/hr/number_card/total_applicants_\050last_month\051/total_applicants_\050last_month\051.json" "b/erpnext/hr/number_card/total_applicants_\050last_month\051/total_applicants_\050last_month\051.json"
new file mode 100644
index 0000000..1af42ca
--- /dev/null
+++ "b/erpnext/hr/number_card/total_applicants_\050last_month\051/total_applicants_\050last_month\051.json"
@@ -0,0 +1,21 @@
+{
+ "creation": "2020-07-22 11:56:32.977716",
+ "docstatus": 0,
+ "doctype": "Number Card",
+ "document_type": "Job Applicant",
+ "dynamic_filters_json": "",
+ "filters_json": "[[\"Job Applicant\",\"creation\",\"Timespan\",\"last month\"]]",
+ "function": "Count",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "label": "Total Applicants (Last month)",
+ "modified": "2020-07-22 14:32:27.656855",
+ "modified_by": "Administrator",
+ "module": "HR",
+ "name": "Total Applicants (Last month)",
+ "owner": "Administrator",
+ "show_percentage_stats": 1,
+ "stats_time_interval": "Monthly",
+ "type": "Document Type"
+}
\ No newline at end of file
diff --git a/erpnext/hr/number_card/total_employees/total_employees.json b/erpnext/hr/number_card/total_employees/total_employees.json
new file mode 100644
index 0000000..932e255
--- /dev/null
+++ b/erpnext/hr/number_card/total_employees/total_employees.json
@@ -0,0 +1,21 @@
+{
+ "creation": "2020-07-22 11:56:32.874849",
+ "docstatus": 0,
+ "doctype": "Number Card",
+ "document_type": "Employee",
+ "dynamic_filters_json": "[[\"Employee\",\"company\",\"=\",\"frappe.defaults.get_user_default(\\\"Company\\\")\"]]",
+ "filters_json": "[[\"Employee\",\"status\",\"=\",\"Active\",false]]",
+ "function": "Count",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "label": "Total Employees",
+ "modified": "2020-07-22 14:31:59.118650",
+ "modified_by": "Administrator",
+ "module": "HR",
+ "name": "Total Employees",
+ "owner": "Administrator",
+ "show_percentage_stats": 1,
+ "stats_time_interval": "Monthly",
+ "type": "Document Type"
+}
\ No newline at end of file
diff --git a/erpnext/hr/report/monthly_attendance_sheet/monthly_attendance_sheet.js b/erpnext/hr/report/monthly_attendance_sheet/monthly_attendance_sheet.js
index bd4ed3c..4b9b928 100644
--- a/erpnext/hr/report/monthly_attendance_sheet/monthly_attendance_sheet.js
+++ b/erpnext/hr/report/monthly_attendance_sheet/monthly_attendance_sheet.js
@@ -5,12 +5,25 @@
 frappe.query_reports["Monthly Attendance Sheet"] = {
 	"filters": [
 		{
-			"fieldname":"month",
+			"fieldname": "month",
 			"label": __("Month"),
 			"fieldtype": "Select",
-			"options": "Jan\nFeb\nMar\nApr\nMay\nJun\nJul\nAug\nSep\nOct\nNov\nDec",
-			"default": ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov",
-				"Dec"][frappe.datetime.str_to_obj(frappe.datetime.get_today()).getMonth()],
+			"reqd": 1 ,
+			"options": [
+				{ "value": 1, "label": __("Jan") },
+				{ "value": 2, "label": __("Feb") },
+				{ "value": 3, "label": __("Mar") },
+				{ "value": 4, "label": __("Apr") },
+				{ "value": 5, "label": __("May") },
+				{ "value": 6, "label": __("June") },
+				{ "value": 7, "label": __("July") },
+				{ "value": 8, "label": __("Aug") },
+				{ "value": 9, "label": __("Sep") },
+				{ "value": 10, "label": __("Oct") },
+				{ "value": 11, "label": __("Nov") },
+				{ "value": 12, "label": __("Dec") },
+			],
+			"default": frappe.datetime.str_to_obj(frappe.datetime.get_today()).getMonth() + 1
 		},
 		{
 			"fieldname":"year",
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 47daab1..4608212 100644
--- a/erpnext/hr/report/monthly_attendance_sheet/monthly_attendance_sheet.py
+++ b/erpnext/hr/report/monthly_attendance_sheet/monthly_attendance_sheet.py
@@ -248,10 +248,7 @@
 	if not (filters.get("month") and filters.get("year")):
 		msgprint(_("Please select month and year"), raise_exception=1)
 
-	filters["month"] = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov",
-		"Dec"].index(filters.month) + 1
-
-	filters["total_days_in_month"] = monthrange(cint(filters.year), filters.month)[1]
+	filters["total_days_in_month"] = monthrange(cint(filters.year), cint(filters.month))[1]
 
 	conditions = " and month(attendance_date) = %(month)s and year(attendance_date) = %(year)s"
 
diff --git a/erpnext/accounts/page/pos/__init__.py b/erpnext/hr/report/recruitment_analytics/__init__.py
similarity index 100%
copy from erpnext/accounts/page/pos/__init__.py
copy to erpnext/hr/report/recruitment_analytics/__init__.py
diff --git a/erpnext/hr/report/recruitment_analytics/recruitment_analytics.js b/erpnext/hr/report/recruitment_analytics/recruitment_analytics.js
new file mode 100644
index 0000000..9620f52
--- /dev/null
+++ b/erpnext/hr/report/recruitment_analytics/recruitment_analytics.js
@@ -0,0 +1,23 @@
+// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+/* eslint-disable */
+
+frappe.query_reports["Recruitment Analytics"] = {
+	"filters": [
+		{
+			"fieldname":"company",
+			"label": __("Company"),
+			"fieldtype": "Link",
+			"options": "Company",
+			"default": frappe.defaults.get_user_default("Company"),
+			"reqd": 1
+		},
+		{
+			"fieldname":"on_date",
+			"label": __("On Date"),
+			"fieldtype": "Date",
+			"default": frappe.datetime.now_date(),
+			"reqd": 1,
+		},
+	]
+};
\ No newline at end of file
diff --git a/erpnext/hr/report/recruitment_analytics/recruitment_analytics.json b/erpnext/hr/report/recruitment_analytics/recruitment_analytics.json
new file mode 100644
index 0000000..30a8e17
--- /dev/null
+++ b/erpnext/hr/report/recruitment_analytics/recruitment_analytics.json
@@ -0,0 +1,27 @@
+{
+ "add_total_row": 0,
+ "creation": "2020-05-14 16:28:45.743869",
+ "disable_prepared_report": 0,
+ "disabled": 0,
+ "docstatus": 0,
+ "doctype": "Report",
+ "idx": 0,
+ "is_standard": "Yes",
+ "modified": "2020-05-14 16:28:45.743869",
+ "modified_by": "Administrator",
+ "module": "HR",
+ "name": "Recruitment Analytics",
+ "owner": "Administrator",
+ "prepared_report": 0,
+ "ref_doctype": "Staffing Plan",
+ "report_name": "Recruitment Analytics",
+ "report_type": "Script Report",
+ "roles": [
+  {
+   "role": "HR Manager"
+  },
+  {
+   "role": "HR User"
+  }
+ ]
+}
\ No newline at end of file
diff --git a/erpnext/hr/report/recruitment_analytics/recruitment_analytics.py b/erpnext/hr/report/recruitment_analytics/recruitment_analytics.py
new file mode 100644
index 0000000..8672094
--- /dev/null
+++ b/erpnext/hr/report/recruitment_analytics/recruitment_analytics.py
@@ -0,0 +1,188 @@
+# 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 _
+
+def execute(filters=None):
+
+	if not filters: filters = {}
+	filters = frappe._dict(filters)
+
+	columns = get_columns()
+
+	data = get_data(filters)
+
+	return columns, data
+
+
+def get_columns():
+	return [
+		{
+			"label": _("Staffing Plan"),
+			"fieldtype": "Link",
+			"fieldname": "staffing_plan",
+			"options": "Staffing Plan",
+			"width": 150
+		},
+		{
+			"label": _("Job Opening"),
+			"fieldtype": "Link",
+			"fieldname": "job_opening",
+			"options": "Job Opening",
+			"width": 100
+		},
+		{
+			"label": _("Job Applicant"),
+			"fieldtype": "Link",
+			"fieldname": "job_applicant",
+			"options": "Job Applicant",
+			"width": 150
+		},
+		{
+			"label": _("Applicant name"),
+			"fieldtype": "data",
+			"fieldname": "applicant_name",
+			"width": 120
+		},
+		{
+			"label": _("Application Status"),
+			"fieldtype": "Data",
+			"fieldname": "application_status",
+			"width": 100
+		},
+		{
+			"label": _("Job Offer"),
+			"fieldtype": "Link",
+			"fieldname": "job_offer",
+			"options": "job Offer",
+			"width": 150
+		},
+		{
+			"label": _("Designation"),
+			"fieldtype": "Data",
+			"fieldname": "designation",
+			"width": 100
+		},
+		{
+			"label": _("Offer Date"),
+			"fieldtype": "date",
+			"fieldname": "offer_date",
+			"width": 100
+		},
+		{
+			"label": _("Job Offer status"),
+			"fieldtype": "Data",
+			"fieldname": "job_offer_status",
+			"width": 150
+		}
+	]
+
+def get_data(filters):
+	data = []
+	staffing_plan_details = get_staffing_plan(filters)
+	staffing_plan_list  = list(set([details["name"] for details in staffing_plan_details]))
+	sp_jo_map , jo_list = get_job_opening(staffing_plan_list)
+	jo_ja_map , ja_list = get_job_applicant(jo_list)
+	ja_joff_map = get_job_offer(ja_list)
+
+	for sp in sp_jo_map.keys():
+		parent_row = get_parent_row(sp_jo_map, sp, jo_ja_map, ja_joff_map)
+		data += parent_row
+
+	return data
+
+
+def get_parent_row(sp_jo_map, sp, jo_ja_map, ja_joff_map):
+	data = []
+	for jo in sp_jo_map[sp]:
+		row = {
+			"staffing_plan" : sp,
+			"job_opening" : jo["name"],
+		}
+		data.append(row)
+		child_row = get_child_row( jo["name"], jo_ja_map, ja_joff_map)
+		data += child_row
+	return data
+
+def get_child_row(jo, jo_ja_map, ja_joff_map):
+	data = []
+	for ja in jo_ja_map[jo]:
+		row = {
+			"indent":1,
+			"job_applicant": ja.name,
+			"applicant_name": ja.applicant_name,
+			"application_status": ja.status,
+		}
+		if ja.name in ja_joff_map.keys():
+			jo_detail =ja_joff_map[ja.name][0]
+			row["job_offer"] = jo_detail.name
+			row["job_offer_status"] = jo_detail.status
+			row["offer_date"]= jo_detail.offer_date.strftime("%d-%m-%Y")
+			row["designation"] = jo_detail.designation
+
+		data.append(row)
+	return data
+
+def get_staffing_plan(filters):
+
+	staffing_plan = frappe.db.sql("""
+	select
+		sp.name, sp.department, spd.designation, spd.vacancies, spd.current_count, spd.parent, sp.to_date
+	from
+		`tabStaffing Plan Detail` spd , `tabStaffing Plan` sp
+	where
+			spd.parent = sp.name
+		And
+			sp.to_date > '{0}'
+		""".format(filters.on_date), as_dict = 1)
+
+	return staffing_plan
+
+def get_job_opening(sp_list):
+
+	job_openings = frappe.get_all("Job Opening", filters = [["staffing_plan", "IN", sp_list]], fields =["name", "staffing_plan"])
+
+	sp_jo_map = {}
+	jo_list = []
+
+	for openings in job_openings:
+		if openings.staffing_plan not in sp_jo_map.keys():
+			sp_jo_map[openings.staffing_plan] = [openings]
+		else:
+			sp_jo_map[openings.staffing_plan].append(openings)
+
+		jo_list.append(openings.name)
+
+	return sp_jo_map, jo_list
+
+def get_job_applicant(jo_list):
+
+	jo_ja_map = {}
+	ja_list =[]
+
+	applicants = frappe.get_all("Job Applicant", filters = [["job_title", "IN", jo_list]], fields =["name", "job_title","applicant_name", 'status'])
+
+	for applicant in applicants:
+		if applicant.job_title not in jo_ja_map.keys():
+			jo_ja_map[applicant.job_title] = [applicant]
+		else:
+			jo_ja_map[applicant.job_title].append(applicant)
+
+		ja_list.append(applicant.name)
+
+	return jo_ja_map , ja_list
+
+def get_job_offer(ja_list):
+	ja_joff_map = {}
+
+	offers = frappe.get_all("Job offer", filters = [["job_applicant", "IN", ja_list]], fields =["name", "job_applicant", "status", 'offer_date', 'designation'])
+
+	for offer in offers:
+		if offer.job_applicant not in ja_joff_map.keys():
+			ja_joff_map[offer.job_applicant] = [offer]
+		else:
+			ja_joff_map[offer.job_applicant].append(offer)
+
+	return ja_joff_map
\ No newline at end of file
diff --git a/erpnext/loan_management/doctype/loan/loan.js b/erpnext/loan_management/doctype/loan/loan.js
index 9cd8b2e..ffef60b 100644
--- a/erpnext/loan_management/doctype/loan/loan.js
+++ b/erpnext/loan_management/doctype/loan/loan.js
@@ -45,15 +45,6 @@
 			});
 		})
 
-		frm.set_query('loan_security_pledge', function(doc, cdt, cdn) {
-			return {
-				filters: {
-					applicant: frm.doc.applicant,
-					docstatus: 1,
-					loan_application: frm.doc.loan_application || ''
-				}
-			};
-		});
 	},
 
 	refresh: function (frm) {
@@ -86,9 +77,6 @@
 		frm.toggle_display("repayment_periods", s1 - frm.doc.is_term_loan);
 	},
 
-	is_secured_loan: function(frm) {
-		frm.toggle_reqd("loan_security_pledge", frm.doc.is_secured_loan);
-	},
 
 	make_loan_disbursement: function (frm) {
 		frappe.call({
diff --git a/erpnext/loan_management/doctype/loan/loan.json b/erpnext/loan_management/doctype/loan/loan.json
index b04e822..192beee 100644
--- a/erpnext/loan_management/doctype/loan/loan.json
+++ b/erpnext/loan_management/doctype/loan/loan.json
@@ -25,15 +25,12 @@
   "disbursement_date",
   "disbursed_amount",
   "column_break_11",
+  "maximum_loan_amount",
   "is_term_loan",
   "repayment_method",
   "repayment_periods",
   "monthly_repayment_amount",
   "repayment_start_date",
-  "loan_security_details_section",
-  "loan_security_pledge",
-  "column_break_25",
-  "maximum_loan_value",
   "account_info",
   "mode_of_payment",
   "payment_account",
@@ -292,13 +289,8 @@
    "default": "0",
    "fieldname": "is_secured_loan",
    "fieldtype": "Check",
-   "label": "Is Secured Loan"
-  },
-  {
-   "depends_on": "is_secured_loan",
-   "fieldname": "loan_security_details_section",
-   "fieldtype": "Section Break",
-   "label": "Loan Security Details"
+   "label": "Is Secured Loan",
+   "read_only": 1
   },
   {
    "default": "0",
@@ -325,12 +317,6 @@
    "read_only": 1
   },
   {
-   "fieldname": "loan_security_pledge",
-   "fieldtype": "Link",
-   "label": "Loan Security Pledge",
-   "options": "Loan Security Pledge"
-  },
-  {
    "fieldname": "disbursed_amount",
    "fieldtype": "Currency",
    "label": "Disbursed Amount",
@@ -338,21 +324,17 @@
    "read_only": 1
   },
   {
-   "fetch_from": "loan_security_pledge.maximum_loan_value",
-   "fieldname": "maximum_loan_value",
+   "fetch_from": "loan_application.maximum_loan_amount",
+   "fieldname": "maximum_loan_amount",
    "fieldtype": "Currency",
-   "label": "Maximum Loan Value",
+   "label": "Maximum Loan Amount",
    "options": "Company:company:default_currency",
    "read_only": 1
-  },
-  {
-   "fieldname": "column_break_25",
-   "fieldtype": "Column Break"
   }
  ],
  "is_submittable": 1,
  "links": [],
- "modified": "2020-04-13 13:16:10.192624",
+ "modified": "2020-07-02 20:46:40.128142",
  "modified_by": "Administrator",
  "module": "Loan Management",
  "name": "Loan",
diff --git a/erpnext/loan_management/doctype/loan/loan.py b/erpnext/loan_management/doctype/loan/loan.py
index 76e10e5..e20b484 100644
--- a/erpnext/loan_management/doctype/loan/loan.py
+++ b/erpnext/loan_management/doctype/loan/loan.py
@@ -13,11 +13,9 @@
 class Loan(AccountsController):
 	def validate(self):
 		self.set_loan_amount()
-
+		self.validate_loan_amount()
 		self.set_missing_fields()
 		self.validate_accounts()
-		self.validate_loan_security_pledge()
-		self.validate_loan_amount()
 		self.check_sanctioned_amount_limit()
 		self.validate_repay_from_salary()
 
@@ -56,21 +54,6 @@
 		if self.repayment_method == "Repay Over Number of Periods":
 			self.monthly_repayment_amount = get_monthly_repayment_amount(self.repayment_method, self.loan_amount, self.rate_of_interest, self.repayment_periods)
 
-	def validate_loan_security_pledge(self):
-
-		if self.is_secured_loan and not self.loan_security_pledge:
-			frappe.throw(_("Loan Security Pledge is mandatory for secured loan"))
-
-		if self.loan_security_pledge:
-			loan_security_details = frappe.db.get_value("Loan Security Pledge", self.loan_security_pledge,
-					['loan', 'company'], as_dict=1)
-
-			if loan_security_details.loan:
-				frappe.throw(_("Loan Security Pledge already pledged against loan {0}").format(loan_security_details.loan))
-
-			if loan_security_details.company != self.company:
-				frappe.throw(_("Loan Security Pledge Company and Loan Company must be same"))
-
 	def check_sanctioned_amount_limit(self):
 		total_loan_amount = get_total_loan_amount(self.applicant_type, self.applicant, self.company)
 		sanctioned_amount_limit = get_sanctioned_amount_limit(self.applicant_type, self.applicant, self.company)
@@ -129,22 +112,29 @@
 			self.total_payment = self.loan_amount
 
 	def set_loan_amount(self):
+		if self.loan_application and not self.loan_amount:
+			self.loan_amount = frappe.db.get_value('Loan Application', self.loan_application, 'loan_amount')
 
-		if not self.loan_amount and self.is_secured_loan and self.loan_security_pledge:
-			self.loan_amount = self.maximum_loan_value
 
 	def validate_loan_amount(self):
-		if self.is_secured_loan and self.loan_amount > self.maximum_loan_value:
-			msg = _("Loan amount cannot be greater than {0}").format(self.maximum_loan_value)
+		if self.maximum_loan_amount and self.loan_amount > self.maximum_loan_amount:
+			msg = _("Loan amount cannot be greater than {0}").format(self.maximum_loan_amount)
 			frappe.throw(msg)
 
 		if not self.loan_amount:
 			frappe.throw(_("Loan amount is mandatory"))
 
 	def link_loan_security_pledge(self):
-		frappe.db.sql("""UPDATE `tabLoan Security Pledge` SET
-			loan = %s, status = 'Pledged', pledge_time = %s
-			where name = %s """, (self.name, now_datetime(), self.loan_security_pledge))
+		if self.is_secured_loan:
+			loan_security_pledge = frappe.db.get_value('Loan Security Pledge', {'loan_application': self.loan_application},
+				'name')
+
+			if loan_security_pledge:
+				frappe.db.set_value('Loan Security Pledge', loan_security_pledge, {
+					'loan': self.name,
+					'status': 'Pledged',
+					'pledge_time': now_datetime()
+				})
 
 	def unlink_loan_security_pledge(self):
 		frappe.db.sql("""UPDATE `tabLoan Security Pledge` SET
@@ -235,8 +225,10 @@
 @frappe.whitelist()
 def create_loan_security_unpledge(loan, applicant_type, applicant, company, as_dict=1):
 	loan_security_pledge_details = frappe.db.sql("""
-		SELECT p.parent, p.loan_security, p.qty as qty FROM `tabLoan Security Pledge` lsp , `tabPledge` p
+		SELECT p.loan_security, sum(p.qty) as qty
+		FROM `tabLoan Security Pledge` lsp , `tabPledge` p
 		WHERE p.parent = lsp.name AND lsp.loan = %s AND lsp.docstatus = 1
+		GROUP BY p.loan_security
 	""",(loan), as_dict=1)
 
 	unpledge_request = frappe.new_doc("Loan Security Unpledge")
diff --git a/erpnext/loan_management/doctype/loan/test_loan.py b/erpnext/loan_management/doctype/loan/test_loan.py
index 3f37a26..c65996e 100644
--- a/erpnext/loan_management/doctype/loan/test_loan.py
+++ b/erpnext/loan_management/doctype/loan/test_loan.py
@@ -16,6 +16,7 @@
 from erpnext.loan_management.doctype.process_loan_security_shortfall.process_loan_security_shortfall import create_process_loan_security_shortfall
 from erpnext.loan_management.doctype.loan.loan import create_loan_security_unpledge
 from erpnext.loan_management.doctype.loan_security_unpledge.loan_security_unpledge import get_pledged_security_qty
+from erpnext.loan_management.doctype.loan_application.loan_application import create_pledge
 
 class TestLoan(unittest.TestCase):
 	def setUp(self):
@@ -72,31 +73,31 @@
 		self.assertEquals(loan.total_payment, 302712)
 
 	def test_loan_with_security(self):
-		pledges = []
-		pledges.append({
+
+		pledge = [{
 			"loan_security": "Test Security 1",
 			"qty": 4000.00,
-			"haircut": 50,
-			"loan_security_price": 500.00
-		})
+		}]
 
-		loan_security_pledge = create_loan_security_pledge(self.applicant2, pledges)
+		loan_application = create_loan_application('_Test Company', self.applicant2,
+			'Stock Loan', pledge, "Repay Over Number of Periods", 12)
+		create_pledge(loan_application)
 
-		loan = create_loan_with_security(self.applicant2, "Stock Loan", "Repay Over Number of Periods", 12, loan_security_pledge.name)
-
+		loan = create_loan_with_security(self.applicant2, "Stock Loan", "Repay Over Number of Periods",
+			12, loan_application)
 		self.assertEquals(loan.loan_amount, 1000000)
 
 	def test_loan_disbursement(self):
-		pledges = []
-		pledges.append({
+		pledge = [{
 			"loan_security": "Test Security 1",
-			"qty": 4000.00,
-			"haircut": 50
-		})
+			"qty": 4000.00
+		}]
 
-		loan_security_pledge = create_loan_security_pledge(self.applicant2, pledges)
+		loan_application = create_loan_application('_Test Company', self.applicant2, 'Stock Loan', pledge, "Repay Over Number of Periods", 12)
 
-		loan = create_loan_with_security(self.applicant2, "Stock Loan", "Repay Over Number of Periods", 12, loan_security_pledge.name)
+		create_pledge(loan_application)
+
+		loan = create_loan_with_security(self.applicant2, "Stock Loan", "Repay Over Number of Periods", 12, loan_application)
 		self.assertEquals(loan.loan_amount, 1000000)
 
 		loan.submit()
@@ -121,18 +122,15 @@
 		self.assertTrue(gl_entries2)
 
 	def test_regular_loan_repayment(self):
-		pledges = []
-		pledges.append({
+		pledge = [{
 			"loan_security": "Test Security 1",
-			"qty": 4000.00,
-			"haircut": 50
-		})
+			"qty": 4000.00
+		}]
 
-		loan_security_pledge = create_loan_security_pledge(self.applicant2, pledges)
+		loan_application = create_loan_application('_Test Company', self.applicant2, 'Demand Loan', pledge)
+		create_pledge(loan_application)
 
-		loan = create_demand_loan(self.applicant2, "Demand Loan", loan_security_pledge.name,
-			posting_date=get_first_day(nowdate()))
-
+		loan = create_demand_loan(self.applicant2, "Demand Loan", loan_application, posting_date=get_first_day(nowdate()))
 		loan.submit()
 
 		self.assertEquals(loan.loan_amount, 1000000)
@@ -166,16 +164,15 @@
 			 penalty_amount - amounts[0], 2))
 
 	def test_loan_closure_repayment(self):
-		pledges = []
-		pledges.append({
+		pledge = [{
 			"loan_security": "Test Security 1",
-			"qty": 4000.00,
-			"haircut": 50
-		})
+			"qty": 4000.00
+		}]
 
-		loan_security_pledge = create_loan_security_pledge(self.applicant2, pledges)
-		loan = create_demand_loan(self.applicant2, "Demand Loan", loan_security_pledge.name,
-			posting_date=get_first_day(nowdate()))
+		loan_application = create_loan_application('_Test Company', self.applicant2, 'Demand Loan', pledge)
+		create_pledge(loan_application)
+
+		loan = create_demand_loan(self.applicant2, "Demand Loan", loan_application, posting_date=get_first_day(nowdate()))
 		loan.submit()
 
 		self.assertEquals(loan.loan_amount, 1000000)
@@ -214,23 +211,21 @@
 		self.assertEquals(loan.status, "Loan Closure Requested")
 
 	def test_loan_repayment_for_term_loan(self):
-		pledges = []
-		pledges.append({
+		pledges = [{
 			"loan_security": "Test Security 2",
-			"qty": 4000.00,
-			"haircut": 50
-		})
-
-		pledges.append({
+			"qty": 4000.00
+		},
+		{
 			"loan_security": "Test Security 1",
-			"qty": 2000.00,
-			"haircut": 50
-		})
+			"qty": 2000.00
+		}]
 
-		loan_security_pledge = create_loan_security_pledge(self.applicant2, pledges)
+		loan_application = create_loan_application('_Test Company', self.applicant2, 'Stock Loan', pledges,
+			"Repay Over Number of Periods", 12)
+		create_pledge(loan_application)
 
-		loan = create_loan_with_security(self.applicant2, "Stock Loan", "Repay Over Number of Periods", 12,
-			loan_security_pledge.name, posting_date=add_months(nowdate(), -1))
+		loan = create_loan_with_security(self.applicant2, "Stock Loan", "Repay Over Number of Periods", 12, loan_application,
+			posting_date=add_months(nowdate(), -1))
 
 		loan.submit()
 
@@ -250,16 +245,18 @@
 		self.assertEquals(amounts[1], 78303.00)
 
 	def test_security_shortfall(self):
-		pledges = []
-		pledges.append({
+		pledges = [{
 			"loan_security": "Test Security 2",
 			"qty": 8000.00,
 			"haircut": 50,
-		})
+		}]
 
-		loan_security_pledge = create_loan_security_pledge(self.applicant2, pledges)
+		loan_application = create_loan_application('_Test Company', self.applicant2,
+			'Stock Loan', pledges, "Repay Over Number of Periods", 12)
 
-		loan = create_loan_with_security(self.applicant2, "Stock Loan", "Repay Over Number of Periods", 12, loan_security_pledge.name)
+		create_pledge(loan_application)
+
+		loan = create_loan_with_security(self.applicant2, "Stock Loan", "Repay Over Number of Periods", 12, loan_application)
 		loan.submit()
 
 		make_loan_disbursement_entry(loan.name, loan.loan_amount)
@@ -279,16 +276,15 @@
 			where loan_security='Test Security 2'""")
 
 	def test_loan_security_unpledge(self):
-		pledges = []
-		pledges.append({
+		pledge = [{
 			"loan_security": "Test Security 1",
-			"qty": 4000.00,
-			"haircut": 50
-		})
+			"qty": 4000.00
+		}]
 
-		loan_security_pledge = create_loan_security_pledge(self.applicant2, pledges)
-		loan = create_demand_loan(self.applicant2, "Demand Loan", loan_security_pledge.name,
-			posting_date=get_first_day(nowdate()))
+		loan_application = create_loan_application('_Test Company', self.applicant2, 'Demand Loan', pledge)
+		create_pledge(loan_application)
+
+		loan = create_demand_loan(self.applicant2, "Demand Loan", loan_application, posting_date=get_first_day(nowdate()))
 		loan.submit()
 
 		self.assertEquals(loan.loan_amount, 1000000)
@@ -446,12 +442,13 @@
 			"haircut": 50.00,
 		}).insert(ignore_permissions=True)
 
-def create_loan_security_pledge(applicant, pledges):
+def create_loan_security_pledge(applicant, pledges, loan_application):
 
 	lsp = frappe.new_doc("Loan Security Pledge")
 	lsp.applicant_type = 'Customer'
 	lsp.applicant = applicant
 	lsp.company = "_Test Company"
+	lsp.loan_application = loan_application
 
 	for pledge in pledges:
 		lsp.append('securities', {
@@ -510,6 +507,31 @@
 
 	return lr
 
+def create_loan_application(company, applicant, loan_type, proposed_pledges, repayment_method=None,
+	repayment_periods=None, posting_date=None):
+	loan_application = frappe.new_doc('Loan Application')
+	loan_application.applicant_type = 'Customer'
+	loan_application.company = company
+	loan_application.applicant = applicant
+	loan_application.loan_type = loan_type
+	loan_application.posting_date = posting_date or nowdate()
+	loan_application.is_secured_loan = 1
+
+	if repayment_method:
+		loan_application.repayment_method = repayment_method
+		loan_application.repayment_periods = repayment_periods
+
+	for pledge in proposed_pledges:
+		loan_application.append('proposed_pledges', pledge)
+
+	loan_application.save()
+	loan_application.submit()
+
+	loan_application.status = 'Approved'
+	loan_application.save()
+
+	return loan_application.name
+
 
 def create_loan(applicant, loan_type, loan_amount, repayment_method, repayment_periods,
 	repayment_start_date=None, posting_date=None):
@@ -531,14 +553,13 @@
 	loan.save()
 	return loan
 
-def create_loan_with_security(applicant, loan_type, repayment_method, repayment_periods, loan_security_pledge,
-	posting_date=None, repayment_start_date=None):
-
+def create_loan_with_security(applicant, loan_type, repayment_method, repayment_periods, loan_application, posting_date=None, repayment_start_date=None):
 	loan = frappe.get_doc({
 		"doctype": "Loan",
 		"company": "_Test Company",
 		"applicant_type": "Customer",
 		"posting_date": posting_date or nowdate(),
+		"loan_application": loan_application,
 		"applicant": applicant,
 		"loan_type": loan_type,
 		"is_term_loan": 1,
@@ -547,7 +568,6 @@
 		"repayment_periods": repayment_periods,
 		"repayment_start_date": repayment_start_date or nowdate(),
 		"mode_of_payment": frappe.db.get_value('Mode of Payment', {'type': 'Cash'}, 'name'),
-		"loan_security_pledge": loan_security_pledge,
 		"payment_account": 'Payment Account - _TC',
 		"loan_account": 'Loan Account - _TC',
 		"interest_income_account": 'Interest Income Account - _TC',
@@ -558,19 +578,19 @@
 
 	return loan
 
-def create_demand_loan(applicant, loan_type, loan_security_pledge, posting_date=None):
+def create_demand_loan(applicant, loan_type, loan_application, posting_date=None):
 
 	loan = frappe.get_doc({
 		"doctype": "Loan",
 		"company": "_Test Company",
 		"applicant_type": "Customer",
 		"posting_date": posting_date or nowdate(),
+		'loan_application': loan_application,
 		"applicant": applicant,
 		"loan_type": loan_type,
 		"is_term_loan": 0,
 		"is_secured_loan": 1,
 		"mode_of_payment": frappe.db.get_value('Mode of Payment', {'type': 'Cash'}, 'name'),
-		"loan_security_pledge": loan_security_pledge,
 		"payment_account": 'Payment Account - _TC',
 		"loan_account": 'Loan Account - _TC',
 		"interest_income_account": 'Interest Income Account - _TC',
diff --git a/erpnext/loan_management/doctype/loan_application/loan_application.py b/erpnext/loan_management/doctype/loan_application/loan_application.py
index d3b8164..f051755 100644
--- a/erpnext/loan_management/doctype/loan_application/loan_application.py
+++ b/erpnext/loan_management/doctype/loan_application/loan_application.py
@@ -103,10 +103,13 @@
 		if self.is_secured_loan and not self.proposed_pledges:
 			frappe.throw(_("Proposed Pledges are mandatory for secured Loans"))
 
-		if not self.loan_amount and self.is_secured_loan and self.proposed_pledges:
-			self.loan_amount = 0
+		if self.is_secured_loan and self.proposed_pledges:
+			self.maximum_loan_amount = 0
 			for security in self.proposed_pledges:
-				self.loan_amount += security.post_haircut_amount
+				self.maximum_loan_amount += security.post_haircut_amount
+
+		if not self.loan_amount and self.is_secured_loan and self.proposed_pledges:
+			self.loan_amount = self.maximum_loan_amount
 
 @frappe.whitelist()
 def create_loan(source_name, target_doc=None, submit=0):
@@ -116,7 +119,6 @@
 		 filters = {'name': source_doc.loan_type}
 		)[0]
 
-		loan_security_pledge = frappe.db.get_value("Loan Security Pledge", {"loan_application": source_name}, 'name')
 
 		target_doc.mode_of_payment = account_details.mode_of_payment
 		target_doc.payment_account = account_details.payment_account
@@ -124,9 +126,6 @@
 		target_doc.interest_income_account = account_details.interest_income_account
 		target_doc.penalty_income_account = account_details.penalty_income_account
 
-		if loan_security_pledge:
-			target_doc.is_secured_loan = 1
-			target_doc.loan_security_pledge = loan_security_pledge
 
 	doclist = get_mapped_doc("Loan Application", source_name, {
 		"Loan Application": {
diff --git a/erpnext/loan_management/doctype/loan_disbursement/test_loan_disbursement.py b/erpnext/loan_management/doctype/loan_disbursement/test_loan_disbursement.py
index 0c1578f..2cb2637 100644
--- a/erpnext/loan_management/doctype/loan_disbursement/test_loan_disbursement.py
+++ b/erpnext/loan_management/doctype/loan_disbursement/test_loan_disbursement.py
@@ -5,11 +5,12 @@
 import frappe
 import unittest
 from frappe.utils import (nowdate, add_days, get_datetime, get_first_day, get_last_day, date_diff, flt, add_to_date)
-from erpnext.loan_management.doctype.loan.test_loan import (create_loan_type, create_loan_security_pledge, create_repayment_entry,
+from erpnext.loan_management.doctype.loan.test_loan import (create_loan_type, create_loan_security_pledge, create_repayment_entry, create_loan_application,
 	make_loan_disbursement_entry, create_loan_accounts, create_loan_security_type, create_loan_security, create_demand_loan, create_loan_security_price)
 from erpnext.loan_management.doctype.process_loan_interest_accrual.process_loan_interest_accrual import process_loan_interest_accrual_for_demand_loans
 from erpnext.loan_management.doctype.loan_interest_accrual.loan_interest_accrual import days_in_year
 from erpnext.selling.doctype.customer.test_customer import get_customer_dict
+from erpnext.loan_management.doctype.loan_application.loan_application import create_pledge
 
 class TestLoanDisbursement(unittest.TestCase):
 
@@ -31,18 +32,15 @@
 		self.applicant = frappe.db.get_value("Customer", {'name': '_Test Loan Customer'}, 'name')
 
 	def test_loan_topup(self):
-		pledges = []
-		pledges.append({
+		pledge = [{
 			"loan_security": "Test Security 1",
-			"qty": 4000.00,
-			"haircut": 50,
-			"loan_security_price": 500.00
-		})
+			"qty": 4000.00
+		}]
 
-		loan_security_pledge = create_loan_security_pledge(self.applicant, pledges)
+		loan_application = create_loan_application('_Test Company', self.applicant, 'Demand Loan', pledge)
+		create_pledge(loan_application)
 
-		loan = create_demand_loan(self.applicant, "Demand Loan", loan_security_pledge.name,
-			posting_date=get_first_day(nowdate()))
+		loan = create_demand_loan(self.applicant, "Demand Loan", loan_application, posting_date=get_first_day(nowdate()))
 
 		loan.submit()
 
diff --git a/erpnext/loan_management/doctype/loan_interest_accrual/test_loan_interest_accrual.py b/erpnext/loan_management/doctype/loan_interest_accrual/test_loan_interest_accrual.py
index 2afed08..4b85b21 100644
--- a/erpnext/loan_management/doctype/loan_interest_accrual/test_loan_interest_accrual.py
+++ b/erpnext/loan_management/doctype/loan_interest_accrual/test_loan_interest_accrual.py
@@ -6,10 +6,11 @@
 import unittest
 from frappe.utils import (nowdate, add_days, get_datetime, get_first_day, get_last_day, date_diff, flt, add_to_date)
 from erpnext.loan_management.doctype.loan.test_loan import (create_loan_type, create_loan_security_pledge, create_loan_security_price,
-	make_loan_disbursement_entry, create_loan_accounts, create_loan_security_type, create_loan_security, create_demand_loan)
+	make_loan_disbursement_entry, create_loan_accounts, create_loan_security_type, create_loan_security, create_demand_loan, create_loan_application)
 from erpnext.loan_management.doctype.process_loan_interest_accrual.process_loan_interest_accrual import process_loan_interest_accrual_for_demand_loans
 from erpnext.loan_management.doctype.loan_interest_accrual.loan_interest_accrual import days_in_year
 from erpnext.selling.doctype.customer.test_customer import get_customer_dict
+from erpnext.loan_management.doctype.loan_application.loan_application import create_pledge
 
 class TestLoanInterestAccrual(unittest.TestCase):
 	def setUp(self):
@@ -29,17 +30,15 @@
 		self.applicant = frappe.db.get_value("Customer", {'name': '_Test Loan Customer'}, 'name')
 
 	def test_loan_interest_accural(self):
-		pledges = []
-		pledges.append({
+		pledge = [{
 			"loan_security": "Test Security 1",
-			"qty": 4000.00,
-			"haircut": 50,
-			"loan_security_price": 500.00
-		})
+			"qty": 4000.00
+		}]
 
-		loan_security_pledge = create_loan_security_pledge(self.applicant, pledges)
+		loan_application = create_loan_application('_Test Company', self.applicant, 'Demand Loan', pledge)
+		create_pledge(loan_application)
 
-		loan = create_demand_loan(self.applicant, "Demand Loan", loan_security_pledge.name,
+		loan = create_demand_loan(self.applicant, "Demand Loan", loan_application,
 			posting_date=get_first_day(nowdate()))
 
 		loan.submit()
diff --git a/erpnext/loan_management/doctype/loan_repayment/loan_repayment.py b/erpnext/loan_management/doctype/loan_repayment/loan_repayment.py
index c28994e..9605045 100644
--- a/erpnext/loan_management/doctype/loan_repayment/loan_repayment.py
+++ b/erpnext/loan_management/doctype/loan_repayment/loan_repayment.py
@@ -116,7 +116,7 @@
 	def allocate_amounts(self, paid_entries):
 		self.set('repayment_details', [])
 		self.principal_amount_paid = 0
-		interest_paid = 0
+		interest_paid = self.amount_paid - self.penalty_amount
 
 		if self.amount_paid - self.penalty_amount > 0 and paid_entries:
 			interest_paid = self.amount_paid - self.penalty_amount
diff --git a/erpnext/loan_management/doctype/loan_security_pledge/loan_security_pledge.json b/erpnext/loan_management/doctype/loan_security_pledge/loan_security_pledge.json
index 1553844..4572e99 100644
--- a/erpnext/loan_management/doctype/loan_security_pledge/loan_security_pledge.json
+++ b/erpnext/loan_management/doctype/loan_security_pledge/loan_security_pledge.json
@@ -1,4 +1,5 @@
 {
+ "actions": [],
  "autoname": "LS-.{applicant}.-.#####",
  "creation": "2019-08-29 18:48:51.371674",
  "doctype": "DocType",
@@ -6,10 +7,10 @@
  "engine": "InnoDB",
  "field_order": [
   "loan_details_section",
-  "loan_application",
-  "loan",
   "applicant_type",
   "applicant",
+  "loan",
+  "loan_application",
   "column_break_3",
   "company",
   "pledge_time",
@@ -55,15 +56,13 @@
    "fieldname": "loan",
    "fieldtype": "Link",
    "label": "Loan",
-   "options": "Loan",
-   "read_only": 1
+   "options": "Loan"
   },
   {
    "fieldname": "loan_application",
    "fieldtype": "Link",
    "label": "Loan Application",
-   "options": "Loan Application",
-   "read_only": 1
+   "options": "Loan Application"
   },
   {
    "fieldname": "total_security_value",
@@ -133,7 +132,8 @@
   }
  ],
  "is_submittable": 1,
- "modified": "2019-10-10 13:22:53.297519",
+ "links": [],
+ "modified": "2020-07-02 23:38:24.002382",
  "modified_by": "Administrator",
  "module": "Loan Management",
  "name": "Loan Security Pledge",
diff --git a/erpnext/loan_management/doctype/loan_security_price/loan_security_price.json b/erpnext/loan_management/doctype/loan_security_price/loan_security_price.json
index db260a4..a55b482 100644
--- a/erpnext/loan_management/doctype/loan_security_price/loan_security_price.json
+++ b/erpnext/loan_management/doctype/loan_security_price/loan_security_price.json
@@ -1,4 +1,5 @@
 {
+ "actions": [],
  "autoname": "LM-LSP-.####",
  "creation": "2019-09-03 18:20:31.382887",
  "doctype": "DocType",
@@ -46,6 +47,7 @@
    "fieldtype": "Currency",
    "in_list_view": 1,
    "label": "Loan Security Price",
+   "options": "Company:company:default_currency",
    "reqd": 1
   },
   {
@@ -79,7 +81,8 @@
    "read_only": 1
   }
  ],
- "modified": "2019-10-26 09:46:46.069667",
+ "links": [],
+ "modified": "2020-06-11 03:41:33.900340",
  "modified_by": "Administrator",
  "module": "Loan Management",
  "name": "Loan Security Price",
diff --git a/erpnext/loan_management/doctype/loan_security_shortfall/loan_security_shortfall.py b/erpnext/loan_management/doctype/loan_security_shortfall/loan_security_shortfall.py
index 308c438..ffd9673 100644
--- a/erpnext/loan_management/doctype/loan_security_shortfall/loan_security_shortfall.py
+++ b/erpnext/loan_management/doctype/loan_security_shortfall/loan_security_shortfall.py
@@ -19,7 +19,9 @@
 		return
 
 	if security_value >= loan_security_shortfall.shortfall_amount:
-		frappe.db.set_value("Loan Security Shortfall", loan_security_shortfall.name, "status", "Completed")
+		frappe.db.set_value("Loan Security Shortfall", loan_security_shortfall.name, {
+			"status": "Completed",
+			"shortfall_value": loan_security_shortfall.shortfall_amount})
 	else:
 		frappe.db.set_value("Loan Security Shortfall", loan_security_shortfall.name,
 			"shortfall_amount", loan_security_shortfall.shortfall_amount - security_value)
diff --git a/erpnext/loan_management/loan_common.js b/erpnext/loan_management/loan_common.js
index 3a47a88..d9dd415 100644
--- a/erpnext/loan_management/loan_common.js
+++ b/erpnext/loan_management/loan_common.js
@@ -9,12 +9,15 @@
 		}
 
 		if (['Loan Disbursement', 'Loan Repayment', 'Loan Interest Accrual'].includes(frm.doc.doctype)
-			&& frm.doc.docstatus == 1) {
+			&& frm.doc.docstatus > 0) {
 
 			frm.add_custom_button(__("Accounting Ledger"), function() {
 				frappe.route_options = {
 					voucher_no: frm.doc.name,
-					company: frm.doc.company
+					company: frm.doc.company,
+					from_date: frm.doc.posting_date,
+					to_date: moment(frm.doc.modified).format('YYYY-MM-DD'),
+					show_cancelled_entries: frm.doc.docstatus === 2
 				};
 
 				frappe.set_route("query-report", "General Ledger");
diff --git a/erpnext/maintenance/doctype/maintenance_schedule/maintenance_schedule.py b/erpnext/maintenance/doctype/maintenance_schedule/maintenance_schedule.py
index b58f999..add7bbf 100644
--- a/erpnext/maintenance/doctype/maintenance_schedule/maintenance_schedule.py
+++ b/erpnext/maintenance/doctype/maintenance_schedule/maintenance_schedule.py
@@ -44,7 +44,7 @@
 		for d in self.get('items'):
 			if d.serial_no:
 				serial_nos = get_valid_serial_nos(d.serial_no)
-				self.validate_serial_no(serial_nos, d.start_date)
+				self.validate_serial_no(d.item_code, serial_nos, d.start_date)
 				self.update_amc_date(serial_nos, d.end_date)
 
 			no_email_sp = []
@@ -178,14 +178,18 @@
 			serial_no_doc.amc_expiry_date = amc_expiry_date
 			serial_no_doc.save()
 
-	def validate_serial_no(self, serial_nos, amc_start_date):
+	def validate_serial_no(self, item_code, serial_nos, amc_start_date):
 		for serial_no in serial_nos:
 			sr_details = frappe.db.get_value("Serial No", serial_no,
-				["warranty_expiry_date", "amc_expiry_date", "warehouse", "delivery_date"], as_dict=1)
+				["warranty_expiry_date", "amc_expiry_date", "warehouse", "delivery_date", "item_code"], as_dict=1)
 
 			if not sr_details:
 				frappe.throw(_("Serial No {0} not found").format(serial_no))
 
+			if sr_details.get("item_code") != item_code:
+				frappe.throw(_("Serial No {0} does not belong to Item {1}")
+					.format(frappe.bold(serial_no), frappe.bold(item_code)), title="Invalid")
+
 			if sr_details.warranty_expiry_date \
 				and getdate(sr_details.warranty_expiry_date) >= getdate(amc_start_date):
 				throw(_("Serial No {0} is under warranty upto {1}")
diff --git a/erpnext/maintenance/doctype/maintenance_visit/maintenance_visit.json b/erpnext/maintenance/doctype/maintenance_visit/maintenance_visit.json
index c797b7e..1192568 100644
--- a/erpnext/maintenance/doctype/maintenance_visit/maintenance_visit.json
+++ b/erpnext/maintenance/doctype/maintenance_visit/maintenance_visit.json
@@ -701,7 +701,7 @@
    "columns": 0, 
    "default": "Draft", 
    "fieldname": "status", 
-   "fieldtype": "Data", 
+   "fieldtype": "Select", 
    "hidden": 0, 
    "ignore_user_permissions": 0, 
    "ignore_xss_filter": 0, 
@@ -1001,7 +1001,7 @@
  "issingle": 0, 
  "istable": 0, 
  "max_attachments": 0, 
- "modified": "2018-08-21 14:44:44.911402", 
+ "modified": "2020-07-15 14:44:44.911402", 
  "modified_by": "Administrator", 
  "module": "Maintenance", 
  "name": "Maintenance Visit", 
diff --git a/erpnext/manufacturing/dashboard_chart/completed_operation/completed_operation.json b/erpnext/manufacturing/dashboard_chart/completed_operation/completed_operation.json
new file mode 100644
index 0000000..d74ae2f
--- /dev/null
+++ b/erpnext/manufacturing/dashboard_chart/completed_operation/completed_operation.json
@@ -0,0 +1,28 @@
+{
+ "based_on": "creation",
+ "chart_name": "Completed Operation",
+ "chart_type": "Sum",
+ "creation": "2020-07-08 22:40:22.441658",
+ "docstatus": 0,
+ "doctype": "Dashboard Chart",
+ "document_type": "Work Order Operation",
+ "filters_json": "[[\"Work Order Operation\",\"docstatus\",\"=\",1,false]]",
+ "group_by_type": "Count",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "last_synced_on": "2020-07-21 16:57:09.767009",
+ "modified": "2020-07-21 16:57:55.719802",
+ "modified_by": "Administrator",
+ "module": "Manufacturing",
+ "name": "Completed Operation",
+ "number_of_groups": 0,
+ "owner": "Administrator",
+ "time_interval": "Quarterly",
+ "timeseries": 1,
+ "timespan": "Last Year",
+ "type": "Line",
+ "use_report_chart": 0,
+ "value_based_on": "completed_qty",
+ "y_axis": []
+}
\ No newline at end of file
diff --git a/erpnext/manufacturing/dashboard_chart/job_card_analysis/job_card_analysis.json b/erpnext/manufacturing/dashboard_chart/job_card_analysis/job_card_analysis.json
new file mode 100644
index 0000000..e3cbba6
--- /dev/null
+++ b/erpnext/manufacturing/dashboard_chart/job_card_analysis/job_card_analysis.json
@@ -0,0 +1,26 @@
+{
+ "chart_name": "Job Card Analysis",
+ "chart_type": "Report",
+ "creation": "2020-07-08 22:40:22.549096",
+ "custom_options": "{\"barOptions\": {\"stacked\": 1}}",
+ "docstatus": 0,
+ "doctype": "Dashboard Chart",
+ "dynamic_filters_json": "{\"company\":\"frappe.defaults.get_user_default(\\\"Company\\\")\",\"from_date\":\"frappe.defaults.get_user_default(\\\"year_start_date\\\")\",\"to_date\":\"frappe.defaults.get_user_default(\\\"year_end_date\\\")\"}",
+ "filters_json": "{\"docstatus\":1,\"range\":\"Monthly\"}",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "modified": "2020-07-21 17:47:06.537924",
+ "modified_by": "Administrator",
+ "module": "Manufacturing",
+ "name": "Job Card Analysis",
+ "number_of_groups": 0,
+ "owner": "Administrator",
+ "report_name": "Job Card Summary",
+ "time_interval": "Yearly",
+ "timeseries": 0,
+ "timespan": "Last Year",
+ "type": "Bar",
+ "use_report_chart": 1,
+ "y_axis": []
+}
\ No newline at end of file
diff --git a/erpnext/manufacturing/dashboard_chart/last_month_downtime_analysis/last_month_downtime_analysis.json b/erpnext/manufacturing/dashboard_chart/last_month_downtime_analysis/last_month_downtime_analysis.json
new file mode 100644
index 0000000..46d2215
--- /dev/null
+++ b/erpnext/manufacturing/dashboard_chart/last_month_downtime_analysis/last_month_downtime_analysis.json
@@ -0,0 +1,26 @@
+{
+ "chart_name": "Last Month Downtime Analysis",
+ "chart_type": "Report",
+ "creation": "2020-07-08 22:40:22.516460",
+ "custom_options": "",
+ "docstatus": 0,
+ "doctype": "Dashboard Chart",
+ "dynamic_filters_json": "{}",
+ "filters_json": "{\"from_date\":\"2020-06-21 00:00:00\",\"to_date\":\"2020-07-21 18:46:45\"}",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "modified": "2020-07-21 18:46:50.767333",
+ "modified_by": "Administrator",
+ "module": "Manufacturing",
+ "name": "Last Month Downtime Analysis",
+ "number_of_groups": 0,
+ "owner": "Administrator",
+ "report_name": "Downtime Analysis",
+ "time_interval": "Yearly",
+ "timeseries": 0,
+ "timespan": "Last Year",
+ "type": "Bar",
+ "use_report_chart": 1,
+ "y_axis": []
+}
\ No newline at end of file
diff --git a/erpnext/manufacturing/dashboard_chart/pending_work_order/pending_work_order.json b/erpnext/manufacturing/dashboard_chart/pending_work_order/pending_work_order.json
new file mode 100644
index 0000000..91cd12b
--- /dev/null
+++ b/erpnext/manufacturing/dashboard_chart/pending_work_order/pending_work_order.json
@@ -0,0 +1,26 @@
+{
+ "chart_name": "Pending Work Order",
+ "chart_type": "Report",
+ "creation": "2020-07-08 22:40:22.499217",
+ "custom_options": "{\"axisOptions\": {\"shortenYAxisNumbers\": 1}, \"height\": 300}",
+ "docstatus": 0,
+ "doctype": "Dashboard Chart",
+ "dynamic_filters_json": "{\"company\":\"frappe.defaults.get_user_default(\\\"Company\\\")\",\"from_date\":\"frappe.defaults.get_user_default(\\\"year_start_date\\\")\",\"to_date\":\"frappe.defaults.get_user_default(\\\"year_end_date\\\")\"}",
+ "filters_json": "{\"charts_based_on\":\"Age\"}",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "modified": "2020-07-21 17:46:42.917598",
+ "modified_by": "Administrator",
+ "module": "Manufacturing",
+ "name": "Pending Work Order",
+ "number_of_groups": 0,
+ "owner": "Administrator",
+ "report_name": "Work Order Summary",
+ "time_interval": "Yearly",
+ "timeseries": 0,
+ "timespan": "Last Year",
+ "type": "Donut",
+ "use_report_chart": 1,
+ "y_axis": []
+}
\ No newline at end of file
diff --git a/erpnext/manufacturing/dashboard_chart/produced_quantity/produced_quantity.json b/erpnext/manufacturing/dashboard_chart/produced_quantity/produced_quantity.json
new file mode 100644
index 0000000..ba1a29d
--- /dev/null
+++ b/erpnext/manufacturing/dashboard_chart/produced_quantity/produced_quantity.json
@@ -0,0 +1,30 @@
+{
+ "based_on": "modified",
+ "chart_name": "Produced Quantity",
+ "chart_type": "Sum",
+ "creation": "2020-07-08 22:40:22.416285",
+ "custom_options": "",
+ "docstatus": 0,
+ "doctype": "Dashboard Chart",
+ "document_type": "Work Order",
+ "dynamic_filters_json": "[[\"Work Order\",\"company\",\"=\",\"frappe.defaults.get_user_default(\\\"Company\\\")\"]]",
+ "filters_json": "[[\"Work Order\",\"docstatus\",\"=\",\"1\",false]]",
+ "group_by_type": "Count",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "last_synced_on": "2020-07-21 17:46:34.058882",
+ "modified": "2020-07-21 17:54:11.233531",
+ "modified_by": "Administrator",
+ "module": "Manufacturing",
+ "name": "Produced Quantity",
+ "number_of_groups": 0,
+ "owner": "Administrator",
+ "time_interval": "Monthly",
+ "timeseries": 1,
+ "timespan": "Last Year",
+ "type": "Line",
+ "use_report_chart": 0,
+ "value_based_on": "produced_qty",
+ "y_axis": []
+}
\ No newline at end of file
diff --git a/erpnext/manufacturing/dashboard_chart/quality_inspection_analysis/quality_inspection_analysis.json b/erpnext/manufacturing/dashboard_chart/quality_inspection_analysis/quality_inspection_analysis.json
new file mode 100644
index 0000000..8388f3d
--- /dev/null
+++ b/erpnext/manufacturing/dashboard_chart/quality_inspection_analysis/quality_inspection_analysis.json
@@ -0,0 +1,25 @@
+{
+ "chart_name": "Quality Inspection Analysis",
+ "chart_type": "Report",
+ "creation": "2020-07-08 22:40:22.483617",
+ "custom_options": "{\"axisOptions\": {\"shortenYAxisNumbers\": 1}, \"height\": 300}",
+ "docstatus": 0,
+ "doctype": "Dashboard Chart",
+ "filters_json": "{\"from_date\":\"2019-07-09\",\"to_date\":\"2020-07-09\"}",
+ "idx": 0,
+ "use_report_chart": 1,
+ "is_public": 1,
+ "is_standard": 1,
+ "modified": "2020-07-09 12:15:51.564487",
+ "modified_by": "Administrator",
+ "module": "Manufacturing",
+ "name": "Quality Inspection Analysis",
+ "number_of_groups": 0,
+ "owner": "Administrator",
+ "report_name": "Quality Inspection Summary",
+ "time_interval": "Yearly",
+ "timeseries": 0,
+ "timespan": "Last Year",
+ "type": "Donut",
+ "y_axis": []
+}
\ No newline at end of file
diff --git a/erpnext/manufacturing/dashboard_chart/work_order_analysis/work_order_analysis.json b/erpnext/manufacturing/dashboard_chart/work_order_analysis/work_order_analysis.json
new file mode 100644
index 0000000..879826a
--- /dev/null
+++ b/erpnext/manufacturing/dashboard_chart/work_order_analysis/work_order_analysis.json
@@ -0,0 +1,26 @@
+{
+ "chart_name": "Work Order Analysis",
+ "chart_type": "Report",
+ "creation": "2020-07-08 22:40:22.465459",
+ "custom_options": "{\"axisOptions\": {\"shortenYAxisNumbers\": 1}, \"height\": 300}",
+ "docstatus": 0,
+ "doctype": "Dashboard Chart",
+ "dynamic_filters_json": "{\"company\":\"frappe.defaults.get_user_default(\\\"Company\\\")\",\"from_date\":\"frappe.defaults.get_user_default(\\\"year_start_date\\\")\",\"to_date\":\"frappe.defaults.get_user_default(\\\"year_end_date\\\")\"}",
+ "filters_json": "{\"charts_based_on\":\"Status\"}",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "modified": "2020-07-21 17:50:23.806007",
+ "modified_by": "Administrator",
+ "module": "Manufacturing",
+ "name": "Work Order Analysis",
+ "number_of_groups": 0,
+ "owner": "Administrator",
+ "report_name": "Work Order Summary",
+ "time_interval": "Yearly",
+ "timeseries": 0,
+ "timespan": "Last Year",
+ "type": "Donut",
+ "use_report_chart": 1,
+ "y_axis": []
+}
\ No newline at end of file
diff --git a/erpnext/manufacturing/dashboard_chart/work_order_qty_analysis/work_order_qty_analysis.json b/erpnext/manufacturing/dashboard_chart/work_order_qty_analysis/work_order_qty_analysis.json
new file mode 100644
index 0000000..9357279
--- /dev/null
+++ b/erpnext/manufacturing/dashboard_chart/work_order_qty_analysis/work_order_qty_analysis.json
@@ -0,0 +1,26 @@
+{
+ "chart_name": "Work Order Qty Analysis",
+ "chart_type": "Report",
+ "creation": "2020-07-08 22:40:22.532889",
+ "custom_options": "{\"barOptions\": {\"stacked\": 1}}",
+ "docstatus": 0,
+ "doctype": "Dashboard Chart",
+ "dynamic_filters_json": "{\"company\":\"frappe.defaults.get_user_default(\\\"Company\\\")\",\"from_date\":\"frappe.defaults.get_user_default(\\\"year_start_date\\\")\",\"to_date\":\"frappe.defaults.get_user_default(\\\"year_end_date\\\")\"}",
+ "filters_json": "{\"charts_based_on\":\"Quantity\"}",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "modified": "2020-07-21 17:46:59.020709",
+ "modified_by": "Administrator",
+ "module": "Manufacturing",
+ "name": "Work Order Qty Analysis",
+ "number_of_groups": 0,
+ "owner": "Administrator",
+ "report_name": "Work Order Summary",
+ "time_interval": "Yearly",
+ "timeseries": 0,
+ "timespan": "Last Year",
+ "type": "Bar",
+ "use_report_chart": 1,
+ "y_axis": []
+}
\ No newline at end of file
diff --git a/erpnext/manufacturing/dashboard_fixtures.py b/erpnext/manufacturing/dashboard_fixtures.py
index 64e4bc6..0e9a21c 100644
--- a/erpnext/manufacturing/dashboard_fixtures.py
+++ b/erpnext/manufacturing/dashboard_fixtures.py
@@ -192,7 +192,7 @@
 		]),
 		"function": "Count",
 		"is_public": 1,
-		"label": _("Monthly Total Work Order"),
+		"label": _("Monthly Total Work Orders"),
 		"show_percentage_stats": 1,
 		"stats_time_interval": "Weekly"
 	},
@@ -207,7 +207,7 @@
 		]),
 		"function": "Count",
 		"is_public": 1,
-		"label": _("Monthly Completed Work Order"),
+		"label": _("Monthly Completed Work Orders"),
 		"show_percentage_stats": 1,
 		"stats_time_interval": "Weekly"
 	},
@@ -221,7 +221,7 @@
 		]),
 		"function": "Count",
 		"is_public": 1,
-		"label": _("Ongoing Job Card"),
+		"label": _("Ongoing Job Cards"),
 		"show_percentage_stats": 1,
 		"stats_time_interval": "Weekly"
 	},
@@ -235,7 +235,7 @@
 		]),
 		"function": "Count",
 		"is_public": 1,
-		"label": _("Monthly Quality Inspection"),
+		"label": _("Monthly Quality Inspections"),
 		"show_percentage_stats": 1,
 		"stats_time_interval": "Weekly"
 	}]
\ No newline at end of file
diff --git a/erpnext/manufacturing/desk_page/manufacturing/manufacturing.json b/erpnext/manufacturing/desk_page/manufacturing/manufacturing.json
index 763f533..8d11294 100644
--- a/erpnext/manufacturing/desk_page/manufacturing/manufacturing.json
+++ b/erpnext/manufacturing/desk_page/manufacturing/manufacturing.json
@@ -94,12 +94,6 @@
    "type": "DocType"
   },
   {
-   "label": "Dashboard",
-   "link_to": "Manufacturing",
-   "restrict_to_domain": "Manufacturing",
-   "type": "Dashboard"
-  },
-  {
    "label": "Forecasting",
    "link_to": "Exponential Smoothing Forecasting",
    "type": "Report"
@@ -119,6 +113,12 @@
    "label": "Production Planning Report",
    "link_to": "Production Planning Report",
    "type": "Report"
-  }
+  },
+  {
+    "label": "Dashboard",
+    "link_to": "Manufacturing",
+    "restrict_to_domain": "Manufacturing",
+    "type": "Dashboard"
+   } 
  ]
 }
\ No newline at end of file
diff --git a/erpnext/manufacturing/doctype/bom/bom.py b/erpnext/manufacturing/doctype/bom/bom.py
index 7d31a1c..8062342 100644
--- a/erpnext/manufacturing/doctype/bom/bom.py
+++ b/erpnext/manufacturing/doctype/bom/bom.py
@@ -494,7 +494,7 @@
 					'image'			: d.image,
 					'stock_uom'		: d.stock_uom,
 					'stock_qty'		: flt(d.stock_qty),
-					'rate'			: d.base_rate,
+					'rate'			: flt(d.base_rate) / flt(d.conversion_factor),
 					'include_item_in_manufacturing': d.include_item_in_manufacturing
 				}))
 
@@ -910,6 +910,7 @@
 
 	return out
 
+@frappe.whitelist()
 def item_query(doctype, txt, searchfield, start, page_len, filters):
 	meta = frappe.get_meta("Item", cached=True)
 	searchfields = meta.get_search_fields()
@@ -989,4 +990,4 @@
 		},
 	}, target_doc, postprocess)
 
-	return doc
\ No newline at end of file
+	return doc
diff --git a/erpnext/manufacturing/doctype/production_plan/production_plan.py b/erpnext/manufacturing/doctype/production_plan/production_plan.py
index 560286e..c889237 100644
--- a/erpnext/manufacturing/doctype/production_plan/production_plan.py
+++ b/erpnext/manufacturing/doctype/production_plan/production_plan.py
@@ -98,11 +98,17 @@
 		elif self.get_items_from == "Material Request":
 			self.get_mr_items()
 
+	def get_so_mr_list(self, field, table):
+		"""Returns a list of Sales Orders or Material Requests from the respective tables"""
+		so_mr_list = [d.get(field) for d in self.get(table) if d.get(field)]
+		return so_mr_list
+
 	def get_so_items(self):
-		so_list = [d.sales_order for d in self.sales_orders if d.sales_order]
-		if not so_list:
-			msgprint(_("Please enter Sales Orders in the above table"))
-			return []
+		# Check for empty table or empty rows
+		if not self.get("sales_orders") or not self.get_so_mr_list("sales_order", "sales_orders"):
+			frappe.throw(_("Please fill the Sales Orders table"), title=_("Sales Orders Required"))
+
+		so_list = self.get_so_mr_list("sales_order", "sales_orders")
 
 		item_condition = ""
 		if self.item_code:
@@ -134,10 +140,11 @@
 		self.calculate_total_planned_qty()
 
 	def get_mr_items(self):
-		mr_list = [d.material_request for d in self.material_requests if d.material_request]
-		if not mr_list:
-			msgprint(_("Please enter Material Requests in the above table"))
-			return []
+		# Check for empty table or empty rows
+		if not self.get("material_requests") or not self.get_so_mr_list("material_request", "material_requests"):
+			frappe.throw(_("Please fill the Material Requests table"), title=_("Material Requests Required"))
+
+		mr_list = self.get_so_mr_list("material_request", "material_requests")
 
 		item_condition = ""
 		if self.item_code:
@@ -628,16 +635,19 @@
 
 	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."))
+	# Check for empty table or empty rows
+	if not po_items or not [row.get('item_code') for row in po_items if row.get('item_code')]:
+		frappe.throw(_("Items to Manufacture are required to pull the Raw Materials associated with it."),
+			title=_("Items Required"))
 
 	company = doc.get('company')
 	ignore_existing_ordered_qty = doc.get('ignore_existing_ordered_qty')
diff --git a/erpnext/manufacturing/doctype/work_order/work_order.py b/erpnext/manufacturing/doctype/work_order/work_order.py
index e2233a3..f962a11 100644
--- a/erpnext/manufacturing/doctype/work_order/work_order.py
+++ b/erpnext/manufacturing/doctype/work_order/work_order.py
@@ -631,6 +631,7 @@
 		bom.set_bom_material_details()
 		return bom
 
+@frappe.whitelist()
 def get_bom_operations(doctype, txt, searchfield, start, page_len, filters):
 	if txt:
 		filters['operation'] = ('like', '%%%s%%' % txt)
diff --git a/erpnext/manufacturing/manufacturing_dashboard/manufacturing/manufacturing.json b/erpnext/manufacturing/manufacturing_dashboard/manufacturing/manufacturing.json
new file mode 100644
index 0000000..314efe7
--- /dev/null
+++ b/erpnext/manufacturing/manufacturing_dashboard/manufacturing/manufacturing.json
@@ -0,0 +1,62 @@
+{
+ "cards": [
+  {
+   "card": "Monthly Total Work Order"
+  },
+  {
+   "card": "Monthly Completed Work Order"
+  },
+  {
+   "card": "Ongoing Job Card"
+  },
+  {
+   "card": "Monthly Quality Inspection"
+  }
+ ],
+ "charts": [
+  {
+   "chart": "Produced Quantity",
+   "width": "Half"
+  },
+  {
+   "chart": "Completed Operation",
+   "width": "Half"
+  },
+  {
+   "chart": "Work Order Analysis",
+   "width": "Half"
+  },
+  {
+   "chart": "Quality Inspection Analysis",
+   "width": "Half"
+  },
+  {
+   "chart": "Pending Work Order",
+   "width": "Half"
+  },
+  {
+   "chart": "Last Month Downtime Analysis",
+   "width": "Half"
+  },
+  {
+   "chart": "Work Order Qty Analysis",
+   "width": "Full"
+  },
+  {
+   "chart": "Job Card Analysis",
+   "width": "Full"
+  }
+ ],
+ "creation": "2020-07-08 22:40:22.626607",
+ "dashboard_name": "Manufacturing",
+ "docstatus": 0,
+ "doctype": "Dashboard",
+ "idx": 0,
+ "is_default": 0,
+ "is_standard": 1,
+ "modified": "2020-07-09 12:39:39.455039",
+ "modified_by": "Administrator",
+ "module": "Manufacturing",
+ "name": "Manufacturing",
+ "owner": "Administrator"
+}
\ No newline at end of file
diff --git a/erpnext/manufacturing/module_onboarding/manufacturing/manufacturing.json b/erpnext/manufacturing/module_onboarding/manufacturing/manufacturing.json
index 952d1f0..7b5747e 100644
--- a/erpnext/manufacturing/module_onboarding/manufacturing/manufacturing.json
+++ b/erpnext/manufacturing/module_onboarding/manufacturing/manufacturing.json
@@ -19,7 +19,7 @@
  "documentation_url": "https://docs.erpnext.com/docs/user/manual/en/manufacturing",
  "idx": 0,
  "is_complete": 0,
- "modified": "2020-05-19 12:51:42.744570",
+ "modified": "2020-07-08 14:05:56.197563",
  "modified_by": "Administrator",
  "module": "Manufacturing",
  "name": "Manufacturing",
@@ -50,8 +50,7 @@
    "step": "Explore Manufacturing Settings"
   }
  ],
- "subtitle": "Products, Raw Materials, BOM, Work Order and more.",
- "success_message": "Manufacturing module is all setup!",
- "title": "Let's Setup Manufacturing Module",
- "user_can_dismiss": 1
+ "subtitle": "Products, Raw Materials, BOM, Work Order, and more.",
+ "success_message": "Manufacturing module is all set up!",
+ "title": "Let's Set Up the Manufacturing Module."
 }
\ No newline at end of file
diff --git a/erpnext/manufacturing/number_card/monthly_completed_work_order/monthly_completed_work_order.json b/erpnext/manufacturing/number_card/monthly_completed_work_order/monthly_completed_work_order.json
new file mode 100644
index 0000000..36c0b9a
--- /dev/null
+++ b/erpnext/manufacturing/number_card/monthly_completed_work_order/monthly_completed_work_order.json
@@ -0,0 +1,19 @@
+{
+ "creation": "2020-07-08 22:40:22.575086",
+ "docstatus": 0,
+ "doctype": "Number Card",
+ "document_type": "Work Order",
+ "filters_json": "[[\"Work Order\",\"status\",\"=\",\"Completed\"],[\"Work Order\",\"docstatus\",\"=\",1],[\"Work Order\",\"creation\",\"between\",[\"2020-06-08\",\"2020-07-08\"]]]",
+ "function": "Count",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "label": "Monthly Completed Work Orders",
+ "modified": "2020-07-09 12:22:54.809813",
+ "modified_by": "Administrator",
+ "module": "Manufacturing",
+ "name": "Monthly Completed Work Order",
+ "owner": "Administrator",
+ "show_percentage_stats": 1,
+ "stats_time_interval": "Weekly"
+}
\ No newline at end of file
diff --git a/erpnext/manufacturing/number_card/monthly_quality_inspection/monthly_quality_inspection.json b/erpnext/manufacturing/number_card/monthly_quality_inspection/monthly_quality_inspection.json
new file mode 100644
index 0000000..91a4536
--- /dev/null
+++ b/erpnext/manufacturing/number_card/monthly_quality_inspection/monthly_quality_inspection.json
@@ -0,0 +1,19 @@
+{
+ "creation": "2020-07-08 22:40:22.606867",
+ "docstatus": 0,
+ "doctype": "Number Card",
+ "document_type": "Quality Inspection",
+ "filters_json": "[[\"Quality Inspection\",\"docstatus\",\"=\",1],[\"Quality Inspection\",\"creation\",\"between\",[\"2020-06-08\",\"2020-07-08\"]]]",
+ "function": "Count",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "label": "Monthly Quality Inspections",
+ "modified": "2020-07-09 12:23:34.838154",
+ "modified_by": "Administrator",
+ "module": "Manufacturing",
+ "name": "Monthly Quality Inspection",
+ "owner": "Administrator",
+ "show_percentage_stats": 1,
+ "stats_time_interval": "Weekly"
+}
\ No newline at end of file
diff --git a/erpnext/manufacturing/number_card/monthly_total_work_order/monthly_total_work_order.json b/erpnext/manufacturing/number_card/monthly_total_work_order/monthly_total_work_order.json
new file mode 100644
index 0000000..80d3b15
--- /dev/null
+++ b/erpnext/manufacturing/number_card/monthly_total_work_order/monthly_total_work_order.json
@@ -0,0 +1,19 @@
+{
+ "creation": "2020-07-08 22:40:22.562715",
+ "docstatus": 0,
+ "doctype": "Number Card",
+ "document_type": "Work Order",
+ "filters_json": "[[\"Work Order\",\"docstatus\",\"=\",1],[\"Work Order\",\"creation\",\"between\",[\"2020-06-08\",\"2020-07-08\"]]]",
+ "function": "Count",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "label": "Monthly Total Work Orders",
+ "modified": "2020-07-09 12:22:25.698795",
+ "modified_by": "Administrator",
+ "module": "Manufacturing",
+ "name": "Monthly Total Work Order",
+ "owner": "Administrator",
+ "show_percentage_stats": 1,
+ "stats_time_interval": "Weekly"
+}
\ No newline at end of file
diff --git a/erpnext/manufacturing/number_card/ongoing_job_card/ongoing_job_card.json b/erpnext/manufacturing/number_card/ongoing_job_card/ongoing_job_card.json
new file mode 100644
index 0000000..ba23ff3
--- /dev/null
+++ b/erpnext/manufacturing/number_card/ongoing_job_card/ongoing_job_card.json
@@ -0,0 +1,19 @@
+{
+ "creation": "2020-07-08 22:40:22.592042",
+ "docstatus": 0,
+ "doctype": "Number Card",
+ "document_type": "Job Card",
+ "filters_json": "[[\"Job Card\",\"status\",\"!=\",\"Completed\"],[\"Job Card\",\"docstatus\",\"=\",1]]",
+ "function": "Count",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "label": "Ongoing Job Cards",
+ "modified": "2020-07-09 12:23:18.218233",
+ "modified_by": "Administrator",
+ "module": "Manufacturing",
+ "name": "Ongoing Job Card",
+ "owner": "Administrator",
+ "show_percentage_stats": 1,
+ "stats_time_interval": "Weekly"
+}
\ No newline at end of file
diff --git a/erpnext/manufacturing/report/bom_variance_report/bom_variance_report.py b/erpnext/manufacturing/report/bom_variance_report/bom_variance_report.py
index c5627e0..e3e440e 100644
--- a/erpnext/manufacturing/report/bom_variance_report/bom_variance_report.py
+++ b/erpnext/manufacturing/report/bom_variance_report/bom_variance_report.py
@@ -19,7 +19,7 @@
 			"options": "Work Order",
 			"width": 120
 		}]
-	
+
 	if not filters.get('bom_no'):
 		columns.extend([
 			{
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index 928c0ab..2fb9d7f 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -14,6 +14,7 @@
 erpnext.patches.v4_0.move_warehouse_user_to_restrictions
 erpnext.patches.v4_0.global_defaults_to_system_settings
 erpnext.patches.v4_0.update_incharge_name_to_sales_person_in_maintenance_schedule
+execute:frappe.reload_doc("accounts", "doctype", "POS Payment Method") #2020-05-28
 execute:frappe.reload_doc("HR", "doctype", "HR Settings") #2020-01-16
 execute:frappe.reload_doc('stock', 'doctype', 'warehouse') # 2017-04-24
 execute:frappe.reload_doc('accounts', 'doctype', 'sales_invoice') # 2016-08-31
@@ -437,7 +438,6 @@
 erpnext.patches.v8_7.sync_india_custom_fields
 erpnext.patches.v8_7.fix_purchase_receipt_status
 erpnext.patches.v8_6.rename_bom_update_tool
-erpnext.patches.v8_7.set_offline_in_pos_settings #11-09-17
 erpnext.patches.v8_9.add_setup_progress_actions #08-09-2017 #26-09-2017 #22-11-2017 #15-12-2017
 erpnext.patches.v8_9.rename_company_sales_target_field
 erpnext.patches.v8_8.set_bom_rate_as_per_uom
@@ -677,6 +677,8 @@
 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.rename_pos_closing_doctype
+erpnext.patches.v13_0.replace_pos_payment_mode_table
 erpnext.patches.v12_0.retain_permission_rules_for_video_doctype
 erpnext.patches.v12_0.remove_duplicate_leave_ledger_entries #2020-05-22
 erpnext.patches.v13_0.patch_to_fix_reverse_linking_in_additional_salary_encashment_and_incentive
@@ -695,13 +697,23 @@
 execute:frappe.delete_doc("Report", "Department Analytics")
 execute:frappe.rename_doc("Desk Page", "Loan Management", "Loan", force=True)
 erpnext.patches.v12_0.update_uom_conversion_factor
+execute:frappe.delete_doc_if_exists("Page", "pos") #29-05-2020
 erpnext.patches.v13_0.delete_old_purchase_reports
 erpnext.patches.v12_0.set_italian_import_supplier_invoice_permissions
+erpnext.patches.v13_0.update_subscription
+erpnext.patches.v12_0.unhide_cost_center_field
 erpnext.patches.v13_0.update_sla_enhancements
 erpnext.patches.v12_0.update_address_template_for_india
+erpnext.patches.v13_0.update_deferred_settings
 erpnext.patches.v12_0.set_multi_uom_in_rfq
 erpnext.patches.v13_0.delete_old_sales_reports
 execute:frappe.delete_doc_if_exists("DocType", "Bank Reconciliation")
 erpnext.patches.v13_0.move_doctype_reports_and_notification_from_hr_to_payroll #22-06-2020
 erpnext.patches.v13_0.move_payroll_setting_separately_from_hr_settings #22-06-2020
 erpnext.patches.v13_0.check_is_income_tax_component #22-06-2020
+erpnext.patches.v13_0.loyalty_points_entry_for_pos_invoice #22-07-2020
+erpnext.patches.v12_0.add_taxjar_integration_field
+erpnext.patches.v13_0.delete_report_requested_items_to_order
+erpnext.patches.v12_0.update_item_tax_template_company
+erpnext.patches.v13_0.move_branch_code_to_bank_account
+erpnext.patches.v13_0.healthcare_lab_module_rename_doctypes
diff --git a/erpnext/patches/v11_0/refactor_autoname_naming.py b/erpnext/patches/v11_0/refactor_autoname_naming.py
index d67c723..5dc5d3b 100644
--- a/erpnext/patches/v11_0/refactor_autoname_naming.py
+++ b/erpnext/patches/v11_0/refactor_autoname_naming.py
@@ -54,7 +54,7 @@
 	'Payroll Entry': 'HR-PRUN-.YYYY.-.#####',
 	'Period Closing Voucher': 'ACC-PCV-.YYYY.-.#####',
 	'Plant Analysis': 'AG-PLA-.YYYY.-.#####',
-	'POS Closing Voucher': 'POS-CLO-.YYYY.-.#####',
+	'POS Closing Entry': 'POS-CLO-.YYYY.-.#####',
 	'Prepared Report': 'SYS-PREP-.YYYY.-.#####',
 	'Program Enrollment': 'EDU-ENR-.YYYY.-.#####',
 	'Quotation Item': '',
diff --git a/erpnext/patches/v12_0/add_taxjar_integration_field.py b/erpnext/patches/v12_0/add_taxjar_integration_field.py
new file mode 100644
index 0000000..4c823e1
--- /dev/null
+++ b/erpnext/patches/v12_0/add_taxjar_integration_field.py
@@ -0,0 +1,12 @@
+from __future__ import unicode_literals
+
+import frappe
+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()
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 82c8f5c..43bd0cc 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
@@ -5,6 +5,8 @@
 def execute():
 
 	frappe.reload_doc('accounts', 'doctype', 'allowed_to_transact_with', force=True)
+	frappe.reload_doc('accounts', 'doctype', 'pricing_rule_detail', force=True)
+	frappe.reload_doc('crm', 'doctype', 'lost_reason_detail', force=True)
 
 	company = frappe.get_all('Company', filters = {'country': 'United States'})
 	if not company:
diff --git a/erpnext/patches/v12_0/move_bank_account_swift_number_to_bank.py b/erpnext/patches/v12_0/move_bank_account_swift_number_to_bank.py
index 1ddbae6..a670ade 100644
--- a/erpnext/patches/v12_0/move_bank_account_swift_number_to_bank.py
+++ b/erpnext/patches/v12_0/move_bank_account_swift_number_to_bank.py
@@ -7,8 +7,7 @@
 	if frappe.db.table_exists('Bank') and frappe.db.table_exists('Bank Account') and frappe.db.has_column('Bank Account', 'swift_number'):
 		frappe.db.sql("""
 			UPDATE `tabBank` b, `tabBank Account` ba
-			SET b.swift_number = ba.swift_number, b.branch_code = ba.branch_code
-			WHERE b.name = ba.bank
+			SET b.swift_number = ba.swift_number WHERE b.name = ba.bank
 		""")
 
 	frappe.reload_doc('accounts', 'doctype', 'bank_account')
diff --git a/erpnext/patches/v12_0/move_item_tax_to_item_tax_template.py b/erpnext/patches/v12_0/move_item_tax_to_item_tax_template.py
index 8889056..06331d7 100644
--- a/erpnext/patches/v12_0/move_item_tax_to_item_tax_template.py
+++ b/erpnext/patches/v12_0/move_item_tax_to_item_tax_template.py
@@ -100,8 +100,10 @@
 				tax_type = None
 			else:
 				company = get_company(parts[-1], parenttype, parent)
-				parent_account = frappe.db.get_value("Account",
-					filters={"account_type": "Tax", "root_type": "Liability", "is_group": 0, "company": company}, fieldname="parent_account")
+				parent_account = frappe.get_value("Account", {"account_name": account_name, "company": company}, "parent_account")
+				if not parent_account:
+					parent_account = frappe.db.get_value("Account",
+						filters={"account_type": "Tax", "root_type": "Liability", "is_group": 0, "company": company}, fieldname="parent_account")
 				if not parent_account:
 					parent_account = frappe.db.get_value("Account",
 						filters={"account_type": "Tax", "root_type": "Liability", "is_group": 1, "company": company})
@@ -115,8 +117,11 @@
 				if not tax_type:
 					account = frappe.new_doc("Account")
 					account.update(filters)
-					account.insert()
-					tax_type = account.name
+					try:
+						account.insert()
+						tax_type = account.name
+					except frappe.DuplicateEntryError:
+						tax_type = frappe.db.get_value("Account", {"account_name": account_name, "company": company}, "name")
 
 		account_type = frappe.get_cached_value("Account", tax_type, "account_type")
 
diff --git a/erpnext/patches/v12_0/rename_pos_closing_doctype.py b/erpnext/patches/v12_0/rename_pos_closing_doctype.py
new file mode 100644
index 0000000..8ca92ef
--- /dev/null
+++ b/erpnext/patches/v12_0/rename_pos_closing_doctype.py
@@ -0,0 +1,25 @@
+# License: GNU General Public License v3. See license.txt
+
+from __future__ import unicode_literals
+import frappe
+
+def execute():
+	if frappe.db.table_exists("POS Closing Voucher"):
+		if not frappe.db.exists("DocType", "POS Closing Entry"):
+			frappe.rename_doc('DocType', 'POS Closing Voucher', 'POS Closing Entry', force=True)
+		
+		if not frappe.db.exists('DocType', 'POS Closing Entry Taxes'):
+			frappe.rename_doc('DocType', 'POS Closing Voucher Taxes', 'POS Closing Entry Taxes', force=True)
+		
+		if not frappe.db.exists('DocType', 'POS Closing Voucher Details'):
+			frappe.rename_doc('DocType', 'POS Closing Voucher Details', 'POS Closing Entry Details', force=True)
+
+		frappe.reload_doc('Accounts', 'doctype', 'POS Closing Entry')
+		frappe.reload_doc('Accounts', 'doctype', 'POS Closing Entry Taxes')
+		frappe.reload_doc('Accounts', 'doctype', 'POS Closing Entry Details')
+
+	if frappe.db.exists("DocType", "POS Closing Voucher"):
+		frappe.delete_doc("DocType", "POS Closing Voucher")
+		frappe.delete_doc("DocType", "POS Closing Voucher Taxes")
+		frappe.delete_doc("DocType", "POS Closing Voucher Details")
+		frappe.delete_doc("DocType", "POS Closing Voucher Invoices")
\ No newline at end of file
diff --git a/erpnext/patches/v12_0/unhide_cost_center_field.py b/erpnext/patches/v12_0/unhide_cost_center_field.py
new file mode 100644
index 0000000..6005ab7
--- /dev/null
+++ b/erpnext/patches/v12_0/unhide_cost_center_field.py
@@ -0,0 +1,13 @@
+# Copyright (c) 2017, Frappe and Contributors
+# License: GNU General Public License v3. See license.txt
+
+from __future__ import unicode_literals
+import frappe
+
+def execute():
+	frappe.db.sql("""
+		DELETE FROM `tabProperty Setter`
+		WHERE doc_type in ('Sales Invoice', 'Purchase Invoice', 'Payment Entry')
+		AND field_name = 'cost_center'
+		AND property = 'hidden'
+	""")
\ No newline at end of file
diff --git a/erpnext/patches/v12_0/update_item_tax_template_company.py b/erpnext/patches/v12_0/update_item_tax_template_company.py
new file mode 100644
index 0000000..f749699
--- /dev/null
+++ b/erpnext/patches/v12_0/update_item_tax_template_company.py
@@ -0,0 +1,13 @@
+from __future__ import unicode_literals
+import frappe
+
+def execute():
+    frappe.reload_doc('accounts', 'doctype', 'item_tax_template')
+
+    item_tax_template_list = frappe.get_list('Item Tax Template')
+    for template in item_tax_template_list:
+        doc = frappe.get_doc('Item Tax Template', template.name)
+        for tax in doc.taxes:
+            doc.company = frappe.get_value('Account', tax.tax_type, 'company')
+            break
+        doc.save()
\ No newline at end of file
diff --git a/erpnext/patches/v13_0/delete_report_requested_items_to_order.py b/erpnext/patches/v13_0/delete_report_requested_items_to_order.py
new file mode 100644
index 0000000..94a9fa8
--- /dev/null
+++ b/erpnext/patches/v13_0/delete_report_requested_items_to_order.py
@@ -0,0 +1,12 @@
+import frappe
+
+def execute():
+	""" Check for one or multiple Auto Email Reports and delete """
+	auto_email_reports = frappe.db.get_values("Auto Email Report", {"report": "Requested Items to Order"}, ["name"])
+	for auto_email_report in auto_email_reports:
+		frappe.delete_doc("Auto Email Report", auto_email_report[0])
+
+	frappe.db.sql("""
+		DELETE FROM `tabReport`
+		WHERE name = 'Requested Items to Order'
+	""")
\ No newline at end of file
diff --git a/erpnext/patches/v13_0/healthcare_lab_module_rename_doctypes.py b/erpnext/patches/v13_0/healthcare_lab_module_rename_doctypes.py
new file mode 100644
index 0000000..5920bf1
--- /dev/null
+++ b/erpnext/patches/v13_0/healthcare_lab_module_rename_doctypes.py
@@ -0,0 +1,51 @@
+from __future__ import unicode_literals
+import frappe
+from frappe.model.utils.rename_field import rename_field
+
+def execute():
+	if frappe.db.exists('DocType', 'Lab Test') and frappe.db.exists('DocType', 'Lab Test Template'):
+		# rename child doctypes
+		doctypes = {
+			'Lab Test Groups': 'Lab Test Group Template',
+			'Normal Test Items': 'Normal Test Result',
+			'Sensitivity Test Items': 'Sensitivity Test Result',
+			'Special Test Items': 'Descriptive Test Result',
+			'Special Test Template': 'Descriptive Test Template'
+		}
+
+		frappe.reload_doc('healthcare', 'doctype', 'lab_test')
+		frappe.reload_doc('healthcare', 'doctype', 'lab_test_template')
+
+		for old_dt, new_dt in doctypes.items():
+			if not frappe.db.table_exists(new_dt) and frappe.db.table_exists(old_dt):
+				frappe.rename_doc('DocType', old_dt, new_dt, force=True)
+				frappe.reload_doc('healthcare', 'doctype', frappe.scrub(new_dt))
+				frappe.delete_doc_if_exists('DocType', old_dt)
+
+		parent_fields = {
+			'Lab Test Group Template': 'lab_test_groups',
+			'Descriptive Test Template': 'descriptive_test_templates',
+			'Normal Test Result': 'normal_test_items',
+			'Sensitivity Test Result': 'sensitivity_test_items',
+			'Descriptive Test Result': 'descriptive_test_items'
+		}
+
+		for doctype, parentfield in parent_fields.items():
+			frappe.db.sql("""
+				UPDATE `tab{0}`
+				SET parentfield = %(parentfield)s
+			""".format(doctype), {'parentfield': parentfield})
+
+		# rename field
+		frappe.reload_doc('healthcare', 'doctype', 'lab_test')
+		if frappe.db.has_column('Lab Test', 'special_toggle'):
+			rename_field('Lab Test', 'special_toggle', 'descriptive_toggle')
+
+	if frappe.db.exists('DocType', 'Lab Test Group Template'):
+		# fix select field option
+		frappe.reload_doc('healthcare', 'doctype', 'lab_test_group_template')
+		frappe.db.sql("""
+			UPDATE `tabLab Test Group Template`
+			SET template_or_new_line = 'Add New Line'
+			WHERE template_or_new_line = 'Add new line'
+		""")
diff --git a/erpnext/patches/v13_0/loyalty_points_entry_for_pos_invoice.py b/erpnext/patches/v13_0/loyalty_points_entry_for_pos_invoice.py
new file mode 100644
index 0000000..ee77340
--- /dev/null
+++ b/erpnext/patches/v13_0/loyalty_points_entry_for_pos_invoice.py
@@ -0,0 +1,20 @@
+# Copyright (c) 2019, Frappe and Contributors
+# License: GNU General Public License v3. See license.txt
+
+from __future__ import unicode_literals
+
+import frappe
+
+def execute():
+	'''`sales_invoice` field from loyalty point entry is splitted into `invoice_type` & `invoice` fields'''
+
+	frappe.reload_doc("Accounts", "doctype", "loyalty_point_entry")
+	
+	if not frappe.db.has_column('Loyalty Point Entry', 'sales_invoice'):
+		return
+
+	frappe.db.sql(
+		"""UPDATE `tabLoyalty Point Entry` lpe
+		SET lpe.`invoice_type` = 'Sales Invoice', lpe.`invoice` = lpe.`sales_invoice`
+		WHERE lpe.`sales_invoice` IS NOT NULL
+		AND (lpe.`invoice` IS NULL OR lpe.`invoice` = '')""")
\ No newline at end of file
diff --git a/erpnext/patches/v13_0/move_branch_code_to_bank_account.py b/erpnext/patches/v13_0/move_branch_code_to_bank_account.py
new file mode 100644
index 0000000..833ae2a
--- /dev/null
+++ b/erpnext/patches/v13_0/move_branch_code_to_bank_account.py
@@ -0,0 +1,17 @@
+# Copyright (c) 2019, Frappe and Contributors
+# License: GNU General Public License v3. See license.txt
+
+from __future__ import unicode_literals
+
+import frappe
+
+def execute():
+
+	frappe.reload_doc('accounts', 'doctype', 'bank_account')
+	frappe.reload_doc('accounts', 'doctype', 'bank')
+
+	if frappe.db.has_column('Bank', 'branch_code') and frappe.db.has_column('Bank Account', 'branch_code'):
+		frappe.db.sql("""UPDATE `tabBank` b, `tabBank Account` ba
+			SET ba.branch_code = b.branch_code
+			WHERE ba.bank = b.name AND
+			ifnull(b.branch_code, '') != '' AND ifnull(ba.branch_code, '') = ''""")
\ No newline at end of file
diff --git a/erpnext/patches/v13_0/replace_pos_payment_mode_table.py b/erpnext/patches/v13_0/replace_pos_payment_mode_table.py
new file mode 100644
index 0000000..4a621b6
--- /dev/null
+++ b/erpnext/patches/v13_0/replace_pos_payment_mode_table.py
@@ -0,0 +1,29 @@
+# Copyright (c) 2019, Frappe and Contributors
+# License: GNU General Public License v3. See license.txt
+
+from __future__ import unicode_literals
+
+import frappe
+
+def execute():
+	frappe.reload_doc("Selling", "doctype", "POS Payment Method")
+	pos_profiles = frappe.get_all("POS Profile")
+
+	for pos_profile in pos_profiles:
+		if not pos_profile.get("payments"): return
+
+		payments = frappe.db.sql("""
+			select idx, parentfield, parenttype, parent, mode_of_payment, `default` from `tabSales Invoice Payment` where parent=%s
+		""", pos_profile.name, as_dict=1)
+		if payments:
+			for payment_mode in payments:
+				pos_payment_method = frappe.new_doc("POS Payment Method")
+				pos_payment_method.idx = payment_mode.idx
+				pos_payment_method.default = payment_mode.default
+				pos_payment_method.mode_of_payment = payment_mode.mode_of_payment
+				pos_payment_method.parent = payment_mode.parent
+				pos_payment_method.parentfield = payment_mode.parentfield
+				pos_payment_method.parenttype = payment_mode.parenttype
+				pos_payment_method.db_insert()
+		
+		frappe.db.sql("""delete from `tabSales Invoice Payment` where parent=%s""", pos_profile.name)
diff --git a/erpnext/patches/v13_0/update_actual_start_and_end_date_in_wo.py b/erpnext/patches/v13_0/update_actual_start_and_end_date_in_wo.py
index 331c559..adfa20e 100644
--- a/erpnext/patches/v13_0/update_actual_start_and_end_date_in_wo.py
+++ b/erpnext/patches/v13_0/update_actual_start_and_end_date_in_wo.py
@@ -6,7 +6,6 @@
 
 import frappe
 from frappe.utils import add_to_date
-from frappe.utils.dashboard import get_config, make_records
 
 def execute():
 	frappe.reload_doc("manufacturing", "doctype", "work_order")
diff --git a/erpnext/patches/v13_0/update_deferred_settings.py b/erpnext/patches/v13_0/update_deferred_settings.py
new file mode 100644
index 0000000..a7d8207
--- /dev/null
+++ b/erpnext/patches/v13_0/update_deferred_settings.py
@@ -0,0 +1,11 @@
+# Copyright (c) 2019, Frappe and Contributors
+# License: GNU General Public License v3. See license.txt
+from __future__ import unicode_literals
+import frappe
+
+def execute():
+	accounts_settings = frappe.get_doc('Accounts Settings', 'Accounts Settings')
+	accounts_settings.book_deferred_entries_based_on = 'Days'
+	accounts_settings.book_deferred_entries_via_journal_entry = 0
+	accounts_settings.submit_journal_entries = 0
+	accounts_settings.save()
\ No newline at end of file
diff --git a/erpnext/patches/v13_0/update_subscription.py b/erpnext/patches/v13_0/update_subscription.py
new file mode 100644
index 0000000..871ebf1
--- /dev/null
+++ b/erpnext/patches/v13_0/update_subscription.py
@@ -0,0 +1,41 @@
+# Copyright (c) 2019, Frappe and Contributors
+# License: GNU General Public License v3. See license.txt
+
+from __future__ import unicode_literals
+import frappe
+from six import iteritems
+
+def execute():
+
+	frappe.reload_doc('accounts', 'doctype', 'subscription')
+	frappe.reload_doc('accounts', 'doctype', 'subscription_invoice')
+	frappe.reload_doc('accounts', 'doctype', 'subscription_plan')
+
+	if frappe.db.has_column('Subscription', 'customer'):
+		frappe.db.sql("""
+			UPDATE `tabSubscription`
+			SET
+				start_date = start,
+				party_type = 'Customer',
+				party = customer,
+				sales_tax_template = tax_template
+			WHERE IFNULL(party,'') = ''
+		""")
+
+	frappe.db.sql("""
+		UPDATE `tabSubscription Invoice`
+		SET document_type = 'Sales Invoice'
+		WHERE IFNULL(document_type, '') = ''
+	""")
+
+	price_determination_map = {
+		'Fixed rate': 'Fixed Rate',
+		'Based on price list': 'Based On Price List'
+	}
+
+	for key, value in iteritems(price_determination_map):
+		frappe.db.sql("""
+			UPDATE `tabSubscription Plan`
+			SET price_determination = %s
+			WHERE price_determination = %s
+		""", (value, key))
\ No newline at end of file
diff --git a/erpnext/patches/v8_7/set_offline_in_pos_settings.py b/erpnext/patches/v8_7/set_offline_in_pos_settings.py
deleted file mode 100644
index 7d2882e..0000000
--- a/erpnext/patches/v8_7/set_offline_in_pos_settings.py
+++ /dev/null
@@ -1,13 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
-	frappe.reload_doc('accounts', 'doctype', 'pos_field')
-	frappe.reload_doc('accounts', 'doctype', 'pos_settings')
-
-	doc = frappe.get_doc('POS Settings')
-	doc.use_pos_in_offline_mode = 1
-	doc.save()
\ No newline at end of file
diff --git "a/erpnext/payroll/dashboard_chart/department_wise_salary\050last_month\051/department_wise_salary\050last_month\051.json" "b/erpnext/payroll/dashboard_chart/department_wise_salary\050last_month\051/department_wise_salary\050last_month\051.json"
new file mode 100644
index 0000000..61ae86f
--- /dev/null
+++ "b/erpnext/payroll/dashboard_chart/department_wise_salary\050last_month\051/department_wise_salary\050last_month\051.json"
@@ -0,0 +1,30 @@
+{
+ "aggregate_function_based_on": "rounded_total",
+ "chart_name": "Department Wise Salary(Last Month)",
+ "chart_type": "Group By",
+ "creation": "2020-07-22 11:56:34.511940",
+ "custom_options": "",
+ "docstatus": 0,
+ "doctype": "Dashboard Chart",
+ "document_type": "Salary Slip",
+ "dynamic_filters_json": "[[\"Salary Slip\",\"company\",\"=\",\"frappe.defaults.get_user_default(\\\"Company\\\")\"]]",
+ "filters_json": "[[\"Salary Slip\",\"docstatus\",\"=\",\"1\",false],[\"Salary Slip\",\"start_date\",\"Timespan\",\"last month\",false]]",
+ "group_by_based_on": "department",
+ "group_by_type": "Sum",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "last_synced_on": "2020-07-22 12:46:05.272076",
+ "modified": "2020-07-22 12:48:12.080992",
+ "modified_by": "Administrator",
+ "module": "Payroll",
+ "name": "Department Wise Salary(Last Month)",
+ "number_of_groups": 0,
+ "owner": "Administrator",
+ "time_interval": "Monthly",
+ "timeseries": 0,
+ "timespan": "Last Year",
+ "type": "Bar",
+ "use_report_chart": 0,
+ "y_axis": []
+}
\ No newline at end of file
diff --git "a/erpnext/payroll/dashboard_chart/designation_wise_salary\050last_month\051/designation_wise_salary\050last_month\051.json" "b/erpnext/payroll/dashboard_chart/designation_wise_salary\050last_month\051/designation_wise_salary\050last_month\051.json"
new file mode 100644
index 0000000..b3c4e59
--- /dev/null
+++ "b/erpnext/payroll/dashboard_chart/designation_wise_salary\050last_month\051/designation_wise_salary\050last_month\051.json"
@@ -0,0 +1,30 @@
+{
+ "aggregate_function_based_on": "rounded_total",
+ "chart_name": "Designation Wise Salary(Last Month)",
+ "chart_type": "Group By",
+ "creation": "2020-07-22 11:56:34.550339",
+ "custom_options": "",
+ "docstatus": 0,
+ "doctype": "Dashboard Chart",
+ "document_type": "Salary Slip",
+ "dynamic_filters_json": "[[\"Salary Slip\",\"company\",\"=\",\"frappe.defaults.get_user_default(\\\"Company\\\")\"]]",
+ "filters_json": "[[\"Salary Slip\",\"docstatus\",\"=\",\"1\",false],[\"Salary Slip\",\"start_date\",\"Timespan\",\"last month\",false]]",
+ "group_by_based_on": "designation",
+ "group_by_type": "Sum",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "last_synced_on": "2020-07-22 12:22:18.412822",
+ "modified": "2020-07-22 12:39:07.923382",
+ "modified_by": "Administrator",
+ "module": "Payroll",
+ "name": "Designation Wise Salary(Last Month)",
+ "number_of_groups": 0,
+ "owner": "Administrator",
+ "time_interval": "Monthly",
+ "timeseries": 0,
+ "timespan": "Last Year",
+ "type": "Bar",
+ "use_report_chart": 0,
+ "y_axis": []
+}
\ No newline at end of file
diff --git a/erpnext/payroll/dashboard_chart/outgoing_salary/outgoing_salary.json b/erpnext/payroll/dashboard_chart/outgoing_salary/outgoing_salary.json
new file mode 100644
index 0000000..c77c8a5
--- /dev/null
+++ b/erpnext/payroll/dashboard_chart/outgoing_salary/outgoing_salary.json
@@ -0,0 +1,29 @@
+{
+ "based_on": "end_date",
+ "chart_name": "Outgoing Salary",
+ "chart_type": "Sum",
+ "creation": "2020-07-22 11:56:34.478848",
+ "custom_options": "",
+ "docstatus": 0,
+ "doctype": "Dashboard Chart",
+ "document_type": "Salary Slip",
+ "dynamic_filters_json": "[[\"Salary Slip\",\"company\",\"=\",\"frappe.defaults.get_user_default(\\\"Company\\\")\"]]",
+ "filters_json": "[[\"Salary Slip\",\"docstatus\",\"=\",\"1\",false]]",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "last_synced_on": "2020-07-22 12:11:27.481231",
+ "modified": "2020-07-22 12:20:05.777715",
+ "modified_by": "Administrator",
+ "module": "Payroll",
+ "name": "Outgoing Salary",
+ "number_of_groups": 0,
+ "owner": "Administrator",
+ "time_interval": "Monthly",
+ "timeseries": 1,
+ "timespan": "Last Year",
+ "type": "Line",
+ "use_report_chart": 0,
+ "value_based_on": "rounded_total",
+ "y_axis": []
+}
\ No newline at end of file
diff --git a/erpnext/payroll/dashboard_fixtures.py b/erpnext/payroll/dashboard_fixtures.py
deleted file mode 100644
index ae7a9ff..0000000
--- a/erpnext/payroll/dashboard_fixtures.py
+++ /dev/null
@@ -1,100 +0,0 @@
-# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-import frappe
-import erpnext
-from erpnext.hr.dashboard_fixtures import get_dashboards_chart_doc, get_number_cards_doc
-import json
-from frappe import _
-
-def get_data():
-	return frappe._dict({
-		"dashboards": get_dashboards(),
-		"charts": get_charts(),
-		"number_cards": get_number_cards(),
-	})
-
-def get_dashboards():
-	dashboards = []
-	dashboards.append(get_payroll_dashboard())
-	return dashboards
-
-def get_payroll_dashboard():
-	return {
-		"name": "Payroll",
-		"dashboard_name": "Payroll",
-		"is_default": 1,
-		"charts": [
-			{ "chart": "Outgoing Salary", "width": "Full"},
-			{ "chart": "Designation Wise Salary(Last Month)", "width": "Half"},
-			{ "chart": "Department Wise Salary(Last Month)", "width": "Half"},
-		],
-		"cards": [
-			{"card": "Total Declaration Submitted"},
-			{"card": "Total Salary Structure"},
-			{"card": "Total Incentive Given(Last month)"},
-			{"card": "Total Outgoing Salary(Last month)"},
-		]
-	}
-
-def get_charts():
-	dashboard_charts= [
-		get_dashboards_chart_doc('Outgoing Salary', "Sum", "Line",
-			document_type = "Salary Slip", based_on="end_date",
-			value_based_on = "rounded_total", time_interval = "Monthly", timeseries = 1,
-			filters_json = json.dumps([["Salary Slip", "docstatus", "=", 1]]))
-	]
-
-	dashboard_charts.append(
-		get_dashboards_chart_doc('Department Wise Salary(Last Month)', "Group By", "Bar",
-			document_type = "Salary Slip", group_by_type="Sum", group_by_based_on="department",
-			time_interval = "Monthly", aggregate_function_based_on = "rounded_total",
-			filters_json = json.dumps([
-				["Salary Slip", "docstatus", "=", 1],
-				["Salary Slip", "start_date", "Previous","1 month"]
-			])
-		)
-	)
-
-	dashboard_charts.append(
-		get_dashboards_chart_doc('Designation Wise Salary(Last Month)', "Group By", "Bar",
-			document_type = "Salary Slip", group_by_type="Sum", group_by_based_on="designation",
-			time_interval = "Monthly", aggregate_function_based_on = "rounded_total",
-			filters_json = json.dumps([
-				["Salary Slip", "docstatus", "=", 1],
-				["Salary Slip", "start_date", "Previous","1 month"]
-			])
-		)
-	)
-
-	return dashboard_charts
-
-def get_number_cards():
-	number_cards = [get_number_cards_doc("Employee Tax Exemption Declaration", "Total Declaration Submitted", filters_json = json.dumps([
-				["Employee Tax Exemption Declaration", "docstatus", "=","1"],
-				["Employee Tax Exemption Declaration","creation","Previous","1 year"]
-			])
-		)]
-
-	number_cards.append(get_number_cards_doc("Employee Incentive", "Total Incentive Given(Last month)",
-		time_interval = "Monthly", func = "Sum", aggregate_function_based_on = "incentive_amount",
-		filters_json = json.dumps([
-			["Employee Incentive", "docstatus", "=", 1],
-			["Employee Incentive","payroll_date","Previous","1 year"]
-		]))
-	)
-
-	number_cards.append(get_number_cards_doc("Salary Slip", "Total Outgoing Salary(Last month)",
-		time_interval = "Monthly", time_span= "Monthly", func = "Sum", aggregate_function_based_on = "rounded_total",
-		filters_json = json.dumps([
-			["Salary Slip", "docstatus", "=", 1],
-			["Salary Slip", "start_date","Previous","1 month"]
-		]))
-	)
-	number_cards.append(get_number_cards_doc("Salary Structure", "Total Salary Structure",
-		filters_json = json.dumps([
-			["Salary Structure", "docstatus", "=", 1]
-		]))
-	)
-
-	return number_cards
\ No newline at end of file
diff --git a/erpnext/payroll/doctype/additional_salary/additional_salary.js b/erpnext/payroll/doctype/additional_salary/additional_salary.js
index fb42b6f..d56cd4e 100644
--- a/erpnext/payroll/doctype/additional_salary/additional_salary.js
+++ b/erpnext/payroll/doctype/additional_salary/additional_salary.js
@@ -8,8 +8,7 @@
 		frm.set_query("employee", function() {
 			return {
 				filters: {
-					company: frm.doc.company,
-					status:  "Active"
+					company: frm.doc.company
 				}
 			};
 		});
diff --git a/erpnext/payroll/doctype/additional_salary/additional_salary.py b/erpnext/payroll/doctype/additional_salary/additional_salary.py
index e369ba7..ef174bd 100644
--- a/erpnext/payroll/doctype/additional_salary/additional_salary.py
+++ b/erpnext/payroll/doctype/additional_salary/additional_salary.py
@@ -33,12 +33,16 @@
 			frappe.throw(_("From Date can not be greater than To Date."))
 
 		if date_of_joining:
-			if getdate(self.payroll_date) < getdate(date_of_joining):
+			if self.payroll_date and getdate(self.payroll_date) < getdate(date_of_joining):
 				frappe.throw(_("Payroll date can not be less than employee's joining date."))
-			elif getdate(self.from_date) < getdate(date_of_joining):
+			elif self.from_date and getdate(self.from_date) < getdate(date_of_joining):
 				frappe.throw(_("From date can not be less than employee's joining date."))
-			elif relieving_date and getdate(self.to_date) > getdate(relieving_date):
+
+		if relieving_date:
+			if self.to_date and getdate(self.to_date) > getdate(relieving_date):
 				frappe.throw(_("To date can not be greater than employee's relieving date."))
+			if self.payroll_date and getdate(self.payroll_date) > getdate(relieving_date):
+				frappe.throw(_("Payroll date can not be greater than employee's relieving date."))
 
 	def get_amount(self, sal_start_date, sal_end_date):
 		start_date = getdate(sal_start_date)
@@ -107,4 +111,4 @@
 
 		existing_salary_components.append(d.salary_component)
 
-	return salary_components_details, additional_salary_details
\ No newline at end of file
+	return salary_components_details, additional_salary_details
diff --git a/erpnext/payroll/doctype/employee_benefit_application/employee_benefit_application.py b/erpnext/payroll/doctype/employee_benefit_application/employee_benefit_application.py
index e166a70..d7d00e6 100644
--- a/erpnext/payroll/doctype/employee_benefit_application/employee_benefit_application.py
+++ b/erpnext/payroll/doctype/employee_benefit_application/employee_benefit_application.py
@@ -222,7 +222,7 @@
 
 	return benefit_amount
 
-
+@frappe.whitelist()
 def get_earning_components(doctype, txt, searchfield, start, page_len, filters):
 	if len(filters) < 2:
 		return {}
diff --git a/erpnext/payroll/doctype/employee_incentive/employee_incentive.py b/erpnext/payroll/doctype/employee_incentive/employee_incentive.py
index 44763fc..84a97f6 100644
--- a/erpnext/payroll/doctype/employee_incentive/employee_incentive.py
+++ b/erpnext/payroll/doctype/employee_incentive/employee_incentive.py
@@ -13,6 +13,7 @@
 		additional_salary = frappe.new_doc('Additional Salary')
 		additional_salary.employee = self.employee
 		additional_salary.salary_component = self.salary_component
+		additional_salary.overwrite_salary_structure_amount = 0
 		additional_salary.amount = self.incentive_amount
 		additional_salary.payroll_date = self.payroll_date
 		additional_salary.company = company
diff --git a/erpnext/payroll/doctype/payroll_entry/payroll_entry.js b/erpnext/payroll/doctype/payroll_entry/payroll_entry.js
index 1ae3553..8d35a7b 100644
--- a/erpnext/payroll/doctype/payroll_entry/payroll_entry.js
+++ b/erpnext/payroll/doctype/payroll_entry/payroll_entry.js
@@ -30,6 +30,7 @@
 				).toggleClass('btn-primary', !(frm.doc.employees || []).length);
 			}
 			if ((frm.doc.employees || []).length) {
+				frm.page.clear_primary_action();
 				frm.page.set_primary_action(__('Create Salary Slips'), () => {
 					frm.save('Submit').then(()=>{
 						frm.page.clear_primary_action();
@@ -49,13 +50,14 @@
 		return frappe.call({
 			doc: frm.doc,
 			method: 'fill_employee_details',
-			callback: function(r) {
-				if (r.docs[0].employees){
-					frm.save();
-					frm.refresh();
-					if(r.docs[0].validate_attendance){
-						render_employee_attendance(frm, r.message);
-					}
+		}).then(r => {
+			if (r.docs && r.docs[0].employees){
+				frm.employees = r.docs[0].employees;
+				frm.dirty();
+				frm.save();
+				frm.refresh();
+				if(r.docs[0].validate_attendance){
+					render_employee_attendance(frm, r.message);
 				}
 			}
 		})
diff --git a/erpnext/payroll/doctype/payroll_entry/payroll_entry.py b/erpnext/payroll/doctype/payroll_entry/payroll_entry.py
index e6bb708..ad9b6d8 100644
--- a/erpnext/payroll/doctype/payroll_entry/payroll_entry.py
+++ b/erpnext/payroll/doctype/payroll_entry/payroll_entry.py
@@ -539,6 +539,7 @@
 	if not_submitted_ss:
 		frappe.msgprint(_("Could not submit some Salary Slips"))
 
+@frappe.whitelist()
 def get_payroll_entries_for_jv(doctype, txt, searchfield, start, page_len, filters):
 	return frappe.db.sql("""
 		select name from `tabPayroll Entry`
diff --git a/erpnext/payroll/doctype/payroll_period/payroll_period.json b/erpnext/payroll/doctype/payroll_period/payroll_period.json
index c919b4f..0e09484 100644
--- a/erpnext/payroll/doctype/payroll_period/payroll_period.json
+++ b/erpnext/payroll/doctype/payroll_period/payroll_period.json
@@ -53,7 +53,7 @@
   }
  ],
  "links": [],
- "modified": "2020-06-22 20:12:32.684189",
+ "modified": "2020-06-29 17:17:12.689089",
  "modified_by": "Administrator",
  "module": "Payroll",
  "name": "Payroll Period",
@@ -96,6 +96,7 @@
    "write": 1
   }
  ],
+ "quick_entry": 1,
  "sort_field": "modified",
  "sort_order": "DESC",
  "track_changes": 1
diff --git a/erpnext/payroll/doctype/retention_bonus/retention_bonus.py b/erpnext/payroll/doctype/retention_bonus/retention_bonus.py
index ed0d36c..b8e56ae 100644
--- a/erpnext/payroll/doctype/retention_bonus/retention_bonus.py
+++ b/erpnext/payroll/doctype/retention_bonus/retention_bonus.py
@@ -26,6 +26,7 @@
 			additional_salary.amount = self.bonus_amount
 			additional_salary.payroll_date = self.bonus_payment_date
 			additional_salary.company = company
+			additional_salary.overwrite_salary_structure_amount = 0
 			additional_salary.ref_doctype = self.doctype
 			additional_salary.ref_docname = self.name
 			additional_salary.submit()
@@ -53,7 +54,7 @@
 				'employee': self.employee,
 				'salary_component': self.salary_component,
 				'payroll_date': self.bonus_payment_date,
-				'company': company,
+				'company': self.company,
 				'docstatus': 1,
 				'ref_doctype': self.doctype,
 				'ref_docname': self.name
diff --git a/erpnext/payroll/doctype/salary_slip/salary_slip.json b/erpnext/payroll/doctype/salary_slip/salary_slip.json
index 663a3ef..27a974a 100644
--- a/erpnext/payroll/doctype/salary_slip/salary_slip.json
+++ b/erpnext/payroll/doctype/salary_slip/salary_slip.json
@@ -74,9 +74,7 @@
    "fieldtype": "Date",
    "in_list_view": 1,
    "label": "Posting Date",
-   "reqd": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "reqd": 1
   },
   {
    "fieldname": "employee",
@@ -89,9 +87,7 @@
    "oldfieldtype": "Link",
    "options": "Employee",
    "reqd": 1,
-   "search_index": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "search_index": 1
   },
   {
    "fetch_from": "employee.employee_name",
@@ -102,9 +98,7 @@
    "label": "Employee Name",
    "oldfieldname": "employee_name",
    "oldfieldtype": "Data",
-   "reqd": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "reqd": 1
   },
   {
    "fetch_from": "employee.department",
@@ -115,20 +109,18 @@
    "oldfieldname": "department",
    "oldfieldtype": "Link",
    "options": "Department",
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "depends_on": "eval:doc.designation",
    "fetch_from": "employee.designation",
    "fieldname": "designation",
-   "fieldtype": "Read Only",
+   "fieldtype": "Link",
    "label": "Designation",
    "oldfieldname": "designation",
    "oldfieldtype": "Link",
-   "show_days": 1,
-   "show_seconds": 1
+   "options": "Designation",
+   "read_only": 1
   },
   {
    "fetch_from": "employee.branch",
@@ -139,16 +131,12 @@
    "oldfieldname": "branch",
    "oldfieldtype": "Link",
    "options": "Branch",
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "column_break1",
    "fieldtype": "Column Break",
    "oldfieldtype": "Column Break",
-   "show_days": 1,
-   "show_seconds": 1,
    "width": "50%"
   },
   {
@@ -156,27 +144,21 @@
    "fieldtype": "Select",
    "label": "Status",
    "options": "Draft\nSubmitted\nCancelled",
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "journal_entry",
    "fieldtype": "Link",
    "label": "Journal Entry",
    "options": "Journal Entry",
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "payroll_entry",
    "fieldtype": "Link",
    "label": "Payroll Entry",
    "options": "Payroll Entry",
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "company",
@@ -186,9 +168,7 @@
    "label": "Company",
    "options": "Company",
    "remember_last_selected_value": 1,
-   "reqd": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "reqd": 1
   },
   {
    "allow_on_submit": 1,
@@ -197,62 +177,46 @@
    "ignore_user_permissions": 1,
    "label": "Letter Head",
    "options": "Letter Head",
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "fieldname": "section_break_10",
-   "fieldtype": "Section Break",
-   "show_days": 1,
-   "show_seconds": 1
+   "fieldtype": "Section Break"
   },
   {
    "default": "0",
    "fieldname": "salary_slip_based_on_timesheet",
    "fieldtype": "Check",
    "label": "Salary Slip Based on Timesheet",
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "start_date",
    "fieldtype": "Date",
-   "label": "Start Date",
-   "show_days": 1,
-   "show_seconds": 1
+   "label": "Start Date"
   },
   {
    "fieldname": "end_date",
    "fieldtype": "Date",
-   "label": "End Date",
-   "show_days": 1,
-   "show_seconds": 1
+   "label": "End Date"
   },
   {
    "fieldname": "column_break_15",
-   "fieldtype": "Column Break",
-   "show_days": 1,
-   "show_seconds": 1
+   "fieldtype": "Column Break"
   },
   {
    "fieldname": "salary_structure",
    "fieldtype": "Link",
    "label": "Salary Structure",
    "options": "Salary Structure",
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "depends_on": "eval:(!doc.salary_slip_based_on_timesheet)",
    "fieldname": "payroll_frequency",
    "fieldtype": "Select",
    "label": "Payroll Frequency",
-   "options": "\nMonthly\nFortnightly\nBimonthly\nWeekly\nDaily",
-   "show_days": 1,
-   "show_seconds": 1
+   "options": "\nMonthly\nFortnightly\nBimonthly\nWeekly\nDaily"
   },
   {
    "fieldname": "total_working_days",
@@ -261,18 +225,14 @@
    "oldfieldname": "total_days_in_month",
    "oldfieldtype": "Int",
    "read_only": 1,
-   "reqd": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "reqd": 1
   },
   {
    "fieldname": "leave_without_pay",
    "fieldtype": "Float",
    "label": "Leave Without Pay",
    "oldfieldname": "leave_without_pay",
-   "oldfieldtype": "Currency",
-   "show_days": 1,
-   "show_seconds": 1
+   "oldfieldtype": "Currency"
   },
   {
    "fieldname": "payment_days",
@@ -281,52 +241,38 @@
    "oldfieldname": "payment_days",
    "oldfieldtype": "Float",
    "read_only": 1,
-   "reqd": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "reqd": 1
   },
   {
    "fieldname": "hourly_wages",
-   "fieldtype": "Section Break",
-   "show_days": 1,
-   "show_seconds": 1
+   "fieldtype": "Section Break"
   },
   {
    "fieldname": "timesheets",
    "fieldtype": "Table",
    "label": "Salary Slip Timesheet",
-   "options": "Salary Slip Timesheet",
-   "show_days": 1,
-   "show_seconds": 1
+   "options": "Salary Slip Timesheet"
   },
   {
    "fieldname": "column_break_20",
-   "fieldtype": "Column Break",
-   "show_days": 1,
-   "show_seconds": 1
+   "fieldtype": "Column Break"
   },
   {
    "fieldname": "total_working_hours",
    "fieldtype": "Float",
    "label": "Total Working Hours",
-   "print_hide_if_no_value": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide_if_no_value": 1
   },
   {
    "fieldname": "hour_rate",
    "fieldtype": "Currency",
    "label": "Hour Rate",
    "options": "Company:company:default_currency",
-   "print_hide_if_no_value": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide_if_no_value": 1
   },
   {
    "fieldname": "section_break_26",
-   "fieldtype": "Section Break",
-   "show_days": 1,
-   "show_seconds": 1
+   "fieldtype": "Section Break"
   },
   {
    "fieldname": "bank_name",
@@ -334,9 +280,7 @@
    "label": "Bank Name",
    "oldfieldname": "bank_name",
    "oldfieldtype": "Data",
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "bank_account_no",
@@ -344,47 +288,34 @@
    "label": "Bank Account No.",
    "oldfieldname": "bank_account_no",
    "oldfieldtype": "Data",
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "section_break_32",
-   "fieldtype": "Section Break",
-   "show_days": 1,
-   "show_seconds": 1
+   "fieldtype": "Section Break"
   },
   {
    "default": "0",
    "fieldname": "deduct_tax_for_unclaimed_employee_benefits",
    "fieldtype": "Check",
-   "label": "Deduct Tax For Unclaimed Employee Benefits",
-   "show_days": 1,
-   "show_seconds": 1
+   "label": "Deduct Tax For Unclaimed Employee Benefits"
   },
   {
    "default": "0",
    "fieldname": "deduct_tax_for_unsubmitted_tax_exemption_proof",
    "fieldtype": "Check",
-   "label": "Deduct Tax For Unsubmitted Tax Exemption Proof",
-   "show_days": 1,
-   "show_seconds": 1
+   "label": "Deduct Tax For Unsubmitted Tax Exemption Proof"
   },
   {
    "fieldname": "earning_deduction",
    "fieldtype": "Section Break",
    "label": "Earning & Deduction",
-   "oldfieldtype": "Section Break",
-   "show_days": 1,
-   "show_seconds": 1
+   "oldfieldtype": "Section Break"
   },
   {
    "fieldname": "earning",
    "fieldtype": "Column Break",
-   "label": "Earning",
    "oldfieldtype": "Column Break",
-   "show_days": 1,
-   "show_seconds": 1,
    "width": "50%"
   },
   {
@@ -393,17 +324,12 @@
    "label": "Earnings",
    "oldfieldname": "earning_details",
    "oldfieldtype": "Table",
-   "options": "Salary Detail",
-   "show_days": 1,
-   "show_seconds": 1
+   "options": "Salary Detail"
   },
   {
    "fieldname": "deduction",
    "fieldtype": "Column Break",
-   "label": "Deduction",
    "oldfieldtype": "Column Break",
-   "show_days": 1,
-   "show_seconds": 1,
    "width": "50%"
   },
   {
@@ -412,16 +338,12 @@
    "label": "Deductions",
    "oldfieldname": "deduction_details",
    "oldfieldtype": "Table",
-   "options": "Salary Detail",
-   "show_days": 1,
-   "show_seconds": 1
+   "options": "Salary Detail"
   },
   {
    "fieldname": "totals",
    "fieldtype": "Section Break",
-   "oldfieldtype": "Section Break",
-   "show_days": 1,
-   "show_seconds": 1
+   "oldfieldtype": "Section Break"
   },
   {
    "fieldname": "gross_pay",
@@ -430,15 +352,11 @@
    "oldfieldname": "gross_pay",
    "oldfieldtype": "Currency",
    "options": "Company:company:default_currency",
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "column_break_25",
-   "fieldtype": "Column Break",
-   "show_days": 1,
-   "show_seconds": 1
+   "fieldtype": "Column Break"
   },
   {
    "fieldname": "total_deduction",
@@ -447,32 +365,24 @@
    "oldfieldname": "total_deduction",
    "oldfieldtype": "Currency",
    "options": "Company:company:default_currency",
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "depends_on": "total_loan_repayment",
    "fieldname": "loan_repayment",
    "fieldtype": "Section Break",
-   "label": "Loan repayment",
-   "show_days": 1,
-   "show_seconds": 1
+   "label": "Loan repayment"
   },
   {
    "fieldname": "loans",
    "fieldtype": "Table",
    "label": "Employee Loan",
    "options": "Salary Slip Loan",
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "fieldname": "section_break_43",
-   "fieldtype": "Section Break",
-   "show_days": 1,
-   "show_seconds": 1
+   "fieldtype": "Section Break"
   },
   {
    "default": "0",
@@ -480,9 +390,7 @@
    "fieldtype": "Currency",
    "label": "Total Principal Amount",
    "options": "Company:company:default_currency",
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "default": "0",
@@ -490,15 +398,11 @@
    "fieldtype": "Currency",
    "label": "Total Interest Amount",
    "options": "Company:company:default_currency",
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "column_break_45",
-   "fieldtype": "Column Break",
-   "show_days": 1,
-   "show_seconds": 1
+   "fieldtype": "Column Break"
   },
   {
    "default": "0",
@@ -506,16 +410,12 @@
    "fieldtype": "Currency",
    "label": "Total Loan Repayment",
    "options": "Company:company:default_currency",
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "net_pay_info",
    "fieldtype": "Section Break",
-   "label": "net pay info",
-   "show_days": 1,
-   "show_seconds": 1
+   "label": "net pay info"
   },
   {
    "description": "Gross Pay - Total Deduction - Loan Repayment",
@@ -525,15 +425,11 @@
    "oldfieldname": "net_pay",
    "oldfieldtype": "Currency",
    "options": "Company:company:default_currency",
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "column_break_53",
-   "fieldtype": "Column Break",
-   "show_days": 1,
-   "show_seconds": 1
+   "fieldtype": "Column Break"
   },
   {
    "bold": 1,
@@ -541,15 +437,11 @@
    "fieldtype": "Currency",
    "label": "Rounded Total",
    "options": "Company:company:default_currency",
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "section_break_55",
-   "fieldtype": "Section Break",
-   "show_days": 1,
-   "show_seconds": 1
+   "fieldtype": "Section Break"
   },
   {
    "description": "Net Pay (in words) will be visible once you save the Salary Slip.",
@@ -558,9 +450,7 @@
    "label": "Total in words",
    "oldfieldname": "net_pay_in_words",
    "oldfieldtype": "Data",
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "amended_from",
@@ -572,9 +462,7 @@
    "oldfieldtype": "Data",
    "options": "Salary Slip",
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fetch_from": "employee.payroll_cost_center",
@@ -583,40 +471,32 @@
    "fieldtype": "Link",
    "label": "Payroll Cost Center",
    "options": "Cost Center",
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "mode_of_payment",
    "fieldtype": "Select",
    "label": "Mode Of Payment",
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "absent_days",
    "fieldtype": "Float",
    "label": "Absent Days",
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "unmarked_days",
    "fieldtype": "Float",
    "hidden": 1,
-   "label": "Unmarked days",
-   "show_days": 1,
-   "show_seconds": 1
+   "label": "Unmarked days"
   }
  ],
  "icon": "fa fa-file-text",
  "idx": 9,
  "is_submittable": 1,
  "links": [],
- "modified": "2020-06-22 14:42:43.921828",
+ "modified": "2020-07-22 12:41:03.659422",
  "modified_by": "Administrator",
  "module": "Payroll",
  "name": "Salary Slip",
diff --git a/erpnext/payroll/doctype/salary_slip/salary_slip.py b/erpnext/payroll/doctype/salary_slip/salary_slip.py
index 2da19b0..1e2983e 100644
--- a/erpnext/payroll/doctype/salary_slip/salary_slip.py
+++ b/erpnext/payroll/doctype/salary_slip/salary_slip.py
@@ -207,7 +207,7 @@
 				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"))
+			frappe.throw(_("Please set Payroll based on in Payroll settings"))
 
 		if payroll_based_on == "Attendance":
 			actual_lwp, absent = self.calculate_lwp_and_absent_days_based_on_attendance(holidays)
@@ -244,15 +244,13 @@
 					for holiday in holidays:
 						if not frappe.db.exists("Attendance", {"employee": self.employee, "attendance_date": holiday, "docstatus": 1 }):
 							self.payment_days += 1
-
-
 		else:
 			self.payment_days = 0
 
 	def get_unmarked_days(self):
 		marked_days = frappe.get_all("Attendance", filters = {
-					"attendance_date": ["between", ['2020-05-1',"2020-05-30"]],
-					"employee": 'HR-EMP-00003',
+					"attendance_date": ["between", [self.start_date, self.end_date]],
+					"employee": self.employee,
 					"docstatus": 1
 				}, fields = ["COUNT(*) as marked_days"])[0].marked_days
 
diff --git a/erpnext/payroll/doctype/salary_slip/test_salary_slip.py b/erpnext/payroll/doctype/salary_slip/test_salary_slip.py
index f42b9ad..37cd89a 100644
--- a/erpnext/payroll/doctype/salary_slip/test_salary_slip.py
+++ b/erpnext/payroll/doctype/salary_slip/test_salary_slip.py
@@ -105,7 +105,7 @@
 		#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)
+		self.assertEqual(flt(ss.gross_pay, 2), flt(gross_pay, 2))
 
 		frappe.db.set_value("Payroll Settings", None, "payroll_based_on", "Leave")
 
@@ -271,6 +271,7 @@
 		# 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`""")
+		frappe.db.sql("""delete from `tabAdditional Salary`""")
 
 		payroll_period = create_payroll_period()
 
diff --git a/erpnext/payroll/doctype/salary_structure/condition_and_formula_help.html b/erpnext/payroll/doctype/salary_structure/condition_and_formula_help.html
index e59d78d..d07a1ab 100644
--- a/erpnext/payroll/doctype/salary_structure/condition_and_formula_help.html
+++ b/erpnext/payroll/doctype/salary_structure/condition_and_formula_help.html
@@ -8,7 +8,7 @@
         Variables from Employee:<br> <code>Employment Type = employment_type</code>, <code>Branch = branch</code> etc.
     </li>
     <li>
-        Variables Salary Slip:<br>
+        Variables from Salary Slip:<br>
         <code>Payment Days = payment_days</code>, <code>Leave without pay = leave_without_pay</code> etc.
     </li>
     <li>
diff --git a/erpnext/payroll/doctype/salary_structure/salary_structure.js b/erpnext/payroll/doctype/salary_structure/salary_structure.js
index ca458f9..ad93a2f 100755
--- a/erpnext/payroll/doctype/salary_structure/salary_structure.js
+++ b/erpnext/payroll/doctype/salary_structure/salary_structure.js
@@ -35,7 +35,9 @@
 
 			d.show()
 		});
-		frm.get_field("conditions_and_formula_variable_and_example").$wrapper.append(frm.doc.filters_html).append(help_button)
+		let help_button_wrapper = frm.get_field("conditions_and_formula_variable_and_example").$wrapper;
+		help_button_wrapper.empty();
+		help_button_wrapper.append(frm.doc.filters_html).append(help_button)
 
 		frm.toggle_reqd(['payroll_frequency'], !frm.doc.salary_slip_based_on_timesheet)
 
diff --git a/erpnext/payroll/doctype/taxable_salary_slab/taxable_salary_slab.json b/erpnext/payroll/doctype/taxable_salary_slab/taxable_salary_slab.json
index ce9512f..94eda4c 100644
--- a/erpnext/payroll/doctype/taxable_salary_slab/taxable_salary_slab.json
+++ b/erpnext/payroll/doctype/taxable_salary_slab/taxable_salary_slab.json
@@ -14,6 +14,7 @@
  ],
  "fields": [
   {
+   "default": "0",
    "fieldname": "from_amount",
    "fieldtype": "Currency",
    "in_list_view": 1,
@@ -27,6 +28,7 @@
    "label": "To Amount"
   },
   {
+   "default": "0",
    "fieldname": "percent_deduction",
    "fieldtype": "Percent",
    "in_list_view": 1,
@@ -51,7 +53,7 @@
  ],
  "istable": 1,
  "links": [],
- "modified": "2020-06-22 23:32:47.253106",
+ "modified": "2020-06-22 18:16:07.596493",
  "modified_by": "Administrator",
  "module": "Payroll",
  "name": "Taxable Salary Slab",
diff --git a/erpnext/payroll/module_onboarding/payroll/payroll.json b/erpnext/payroll/module_onboarding/payroll/payroll.json
index a4ea536..b5226b2 100644
--- a/erpnext/payroll/module_onboarding/payroll/payroll.json
+++ b/erpnext/payroll/module_onboarding/payroll/payroll.json
@@ -13,7 +13,7 @@
  "documentation_url": "https://docs.erpnext.com/docs/user/manual/en/human-resources/payroll-entry",
  "idx": 0,
  "is_complete": 0,
- "modified": "2020-06-04 16:35:30.650792",
+ "modified": "2020-07-08 14:06:13.994310",
  "modified_by": "Administrator",
  "module": "Payroll",
  "name": "Payroll",
@@ -44,8 +44,7 @@
    "step": "Payroll Settings"
   }
  ],
- "subtitle": "Salary, Compensations and more.",
- "success_message": "The Payroll is all set up!",
- "title": "Let's Setup the Payroll Module. ",
- "user_can_dismiss": 1
+ "subtitle": "Salary, Compensation, and more.",
+ "success_message": "The Payroll Module is all set up!",
+ "title": "Let's Set Up the Payroll Module. "
 }
\ No newline at end of file
diff --git a/erpnext/payroll/number_card/total_declaration_submitted/total_declaration_submitted.json b/erpnext/payroll/number_card/total_declaration_submitted/total_declaration_submitted.json
new file mode 100644
index 0000000..fa5739b
--- /dev/null
+++ b/erpnext/payroll/number_card/total_declaration_submitted/total_declaration_submitted.json
@@ -0,0 +1,21 @@
+{
+ "creation": "2020-07-22 11:56:34.575627",
+ "docstatus": 0,
+ "doctype": "Number Card",
+ "document_type": "Employee Tax Exemption Declaration",
+ "dynamic_filters_json": "[[\"Employee Tax Exemption Declaration\",\"company\",\"=\",\"frappe.defaults.get_user_default(\\\"Company\\\")\"]]",
+ "filters_json": "[[\"Employee Tax Exemption Declaration\",\"creation\",\"Timespan\",\"last year\",false],[\"Employee Tax Exemption Declaration\",\"docstatus\",\"=\",\"1\",false]]",
+ "function": "Count",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "label": "Total Declaration Submitted",
+ "modified": "2020-07-22 13:22:46.001099",
+ "modified_by": "Administrator",
+ "module": "Payroll",
+ "name": "Total Declaration Submitted",
+ "owner": "Administrator",
+ "show_percentage_stats": 1,
+ "stats_time_interval": "Monthly",
+ "type": "Document Type"
+}
\ No newline at end of file
diff --git "a/erpnext/payroll/number_card/total_incentive_given\050last_month\051/total_incentive_given\050last_month\051.json" "b/erpnext/payroll/number_card/total_incentive_given\050last_month\051/total_incentive_given\050last_month\051.json"
new file mode 100644
index 0000000..2106706
--- /dev/null
+++ "b/erpnext/payroll/number_card/total_incentive_given\050last_month\051/total_incentive_given\050last_month\051.json"
@@ -0,0 +1,22 @@
+{
+ "aggregate_function_based_on": "incentive_amount",
+ "creation": "2020-07-22 11:56:34.599047",
+ "docstatus": 0,
+ "doctype": "Number Card",
+ "document_type": "Employee Incentive",
+ "dynamic_filters_json": "",
+ "filters_json": "[[\"Employee Incentive\",\"docstatus\",\"=\",\"1\",false],[\"Employee Incentive\",\"payroll_date\",\"Timespan\",\"last year\",false]]",
+ "function": "Sum",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "label": "Total Incentive Given(Last month)",
+ "modified": "2020-07-23 12:05:26.963616",
+ "modified_by": "Administrator",
+ "module": "Payroll",
+ "name": "Total Incentive Given(Last month)",
+ "owner": "Administrator",
+ "show_percentage_stats": 1,
+ "stats_time_interval": "Monthly",
+ "type": "Document Type"
+}
\ No newline at end of file
diff --git "a/erpnext/payroll/number_card/total_outgoing_salary\050last_month\051/total_outgoing_salary\050last_month\051.json" "b/erpnext/payroll/number_card/total_outgoing_salary\050last_month\051/total_outgoing_salary\050last_month\051.json"
new file mode 100644
index 0000000..44ee722
--- /dev/null
+++ "b/erpnext/payroll/number_card/total_outgoing_salary\050last_month\051/total_outgoing_salary\050last_month\051.json"
@@ -0,0 +1,22 @@
+{
+ "aggregate_function_based_on": "rounded_total",
+ "creation": "2020-07-22 11:56:34.626019",
+ "docstatus": 0,
+ "doctype": "Number Card",
+ "document_type": "Salary Slip",
+ "dynamic_filters_json": "[[\"Salary Slip\",\"company\",\"=\",\"frappe.defaults.get_user_default(\\\"Company\\\")\"]]",
+ "filters_json": "[[\"Salary Slip\",\"docstatus\",\"=\",\"1\",false],[\"Salary Slip\",\"start_date\",\"Timespan\",\"last month\",false]]",
+ "function": "Sum",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "label": "Total Outgoing Salary(Last month)",
+ "modified": "2020-07-22 13:54:14.678954",
+ "modified_by": "Administrator",
+ "module": "Payroll",
+ "name": "Total Outgoing Salary(Last month)",
+ "owner": "Administrator",
+ "show_percentage_stats": 1,
+ "stats_time_interval": "Monthly",
+ "type": "Document Type"
+}
\ No newline at end of file
diff --git a/erpnext/payroll/number_card/total_salary_structure/total_salary_structure.json b/erpnext/payroll/number_card/total_salary_structure/total_salary_structure.json
new file mode 100644
index 0000000..030935f
--- /dev/null
+++ b/erpnext/payroll/number_card/total_salary_structure/total_salary_structure.json
@@ -0,0 +1,21 @@
+{
+ "creation": "2020-07-22 11:56:34.688843",
+ "docstatus": 0,
+ "doctype": "Number Card",
+ "document_type": "Salary Structure",
+ "dynamic_filters_json": "[[\"Salary Structure\",\"company\",\"=\",\"frappe.defaults.get_user_default(\\\"Company\\\")\"]]",
+ "filters_json": "[[\"Salary Structure\",\"docstatus\",\"=\",\"1\",false]]",
+ "function": "Count",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "label": "Total Salary Structure",
+ "modified": "2020-07-22 13:24:03.938846",
+ "modified_by": "Administrator",
+ "module": "Payroll",
+ "name": "Total Salary Structure",
+ "owner": "Administrator",
+ "show_percentage_stats": 1,
+ "stats_time_interval": "Monthly",
+ "type": "Document Type"
+}
\ No newline at end of file
diff --git a/erpnext/payroll/onboarding_step/create_employee/create_employee.json b/erpnext/payroll/onboarding_step/create_employee/create_employee.json
index 5839ae6..3aa33c6 100644
--- a/erpnext/payroll/onboarding_step/create_employee/create_employee.json
+++ b/erpnext/payroll/onboarding_step/create_employee/create_employee.json
@@ -15,5 +15,5 @@
  "reference_document": "Employee",
  "show_full_form": 0,
  "title": "Create Employee",
- "validate_action": 1
+ "validate_action": 0
 }
\ No newline at end of file
diff --git a/erpnext/payroll/payroll_dashboard/payroll/payroll.json b/erpnext/payroll/payroll_dashboard/payroll/payroll.json
new file mode 100644
index 0000000..fb49d88
--- /dev/null
+++ b/erpnext/payroll/payroll_dashboard/payroll/payroll.json
@@ -0,0 +1,42 @@
+{
+ "cards": [
+  {
+   "card": "Total Declaration Submitted"
+  },
+  {
+   "card": "Total Salary Structure"
+  },
+  {
+   "card": "Total Incentive Given(Last month)"
+  },
+  {
+   "card": "Total Outgoing Salary(Last month)"
+  }
+ ],
+ "charts": [
+  {
+   "chart": "Outgoing Salary",
+   "width": "Full"
+  },
+  {
+   "chart": "Designation Wise Salary(Last Month)",
+   "width": "Half"
+  },
+  {
+   "chart": "Department Wise Salary(Last Month)",
+   "width": "Half"
+  }
+ ],
+ "creation": "2020-07-22 11:56:34.727185",
+ "dashboard_name": "Payroll",
+ "docstatus": 0,
+ "doctype": "Dashboard",
+ "idx": 0,
+ "is_default": 1,
+ "is_standard": 1,
+ "modified": "2020-07-22 13:20:18.608969",
+ "modified_by": "Administrator",
+ "module": "Payroll",
+ "name": "Payroll",
+ "owner": "Administrator"
+}
\ No newline at end of file
diff --git a/erpnext/payroll/report/bank_remittance/bank_remittance.py b/erpnext/payroll/report/bank_remittance/bank_remittance.py
index a35d8e5..4b052bf 100644
--- a/erpnext/payroll/report/bank_remittance/bank_remittance.py
+++ b/erpnext/payroll/report/bank_remittance/bank_remittance.py
@@ -152,6 +152,9 @@
 		company_accounts_map[acc.account] = acc
 
 	for entry in payroll_entries:
-		entry["company_account"] = company_accounts_map[entry.payment_account]['bank_account_no']
+		company_account = ''
+		if entry.payment_account in company_accounts_map:
+			company_account = company_accounts_map[entry.payment_account]['bank_account_no']
+		entry["company_account"] = company_account
 
 	return payroll_entries
diff --git a/erpnext/payroll/report/income_tax_deductions/income_tax_deductions.py b/erpnext/payroll/report/income_tax_deductions/income_tax_deductions.py
index 3bad587..8a79416 100644
--- a/erpnext/payroll/report/income_tax_deductions/income_tax_deductions.py
+++ b/erpnext/payroll/report/income_tax_deductions/income_tax_deductions.py
@@ -6,8 +6,8 @@
 from frappe import _
 
 def execute(filters=None):
-	columns = get_columns(filters)
 	data = get_data(filters)
+	columns = get_columns(filters) if len(data) else []
 
 	return columns, data
 
@@ -78,8 +78,11 @@
 	if filters.get("company"):
 		conditions.append("sal.company = '%s' " % (filters["company"]) )
 
-	if filters.get("period"):
-		conditions.append("month(sal.start_date) = '%s' " % (filters["period"]))
+	if filters.get("month"):
+		conditions.append("month(sal.start_date) = '%s' " % (filters["month"]))
+
+	if filters.get("year"):
+		conditions.append("year(start_date) = '%s' " % (filters["year"]))
 
 	return " and ".join(conditions)
 
@@ -96,6 +99,9 @@
 
 	component_types = [comp_type[0] for comp_type in component_types]
 
+	if not len(component_types):
+		return []
+
 	conditions = get_conditions(filters)
 
 	entry = frappe.db.sql(""" select sal.employee, sal.employee_name, sal.posting_date, ded.salary_component, ded.amount,sal.gross_pay
diff --git a/erpnext/payroll/report/salary_payments_based_on_payment_mode/salary_payments_based_on_payment_mode.py b/erpnext/payroll/report/salary_payments_based_on_payment_mode/salary_payments_based_on_payment_mode.py
index 7f0c2e2..a0dab63 100644
--- a/erpnext/payroll/report/salary_payments_based_on_payment_mode/salary_payments_based_on_payment_mode.py
+++ b/erpnext/payroll/report/salary_payments_based_on_payment_mode/salary_payments_based_on_payment_mode.py
@@ -100,6 +100,8 @@
 	total_row = get_total_based_on_mode_of_payment(data, mode_of_payments)
 	total_deductions = gross_pay - total_row.get("total")
 
+	report_summary = []
+
 	if data:
 		data.append(total_row)
 		data.append({})
diff --git a/erpnext/payroll/report/salary_payments_via_ecs/salary_payments_via_ecs.py b/erpnext/payroll/report/salary_payments_via_ecs/salary_payments_via_ecs.py
index 073bd91..d09745c 100644
--- a/erpnext/payroll/report/salary_payments_via_ecs/salary_payments_via_ecs.py
+++ b/erpnext/payroll/report/salary_payments_via_ecs/salary_payments_via_ecs.py
@@ -84,9 +84,11 @@
 	if filters.get("company"):
 		conditions.append("company = '%s' " % (filters["company"]) )
 
-	if filters.get("period"):
-		conditions.append("month(start_date) = '%s' " % (filters["period"]))
-		conditions.append("year(start_date) = '%s' " % (frappe.utils.getdate().year))
+	if filters.get("month"):
+		conditions.append("month(start_date) = '%s' " % (filters["month"]))
+
+	if filters.get("year"):
+		conditions.append("year(start_date) = '%s' " % (filters["year"]))
 
 	return " and ".join(conditions)
 
diff --git a/erpnext/portal/doctype/products_settings/products_settings.py b/erpnext/portal/doctype/products_settings/products_settings.py
index 82afebf..b984aeb 100644
--- a/erpnext/portal/doctype/products_settings/products_settings.py
+++ b/erpnext/portal/doctype/products_settings/products_settings.py
@@ -11,9 +11,9 @@
 class ProductsSettings(Document):
 	def validate(self):
 		if self.home_page_is_products:
-			website_settings = frappe.get_doc('Website Settings')
-			website_settings.home_page = 'products'
-			website_settings.save()
+			frappe.db.set_value("Website Settings", "home_page", "products")
+		elif frappe.db.get_single_value("Website Settings", "home_page") == 'products':
+			frappe.db.set_value("Website Settings", "home_page", "home")
 
 		self.validate_field_filters()
 		self.validate_attribute_filters()
@@ -40,4 +40,3 @@
 	home_page_is_products = cint(frappe.db.get_single_value('Products Settings', 'home_page_is_products'))
 	if home_page_is_products:
 		doc.home_page = 'products'
-
diff --git a/erpnext/portal/product_configurator/utils.py b/erpnext/portal/product_configurator/utils.py
index 6b6b8c5..f8af30a 100644
--- a/erpnext/portal/product_configurator/utils.py
+++ b/erpnext/portal/product_configurator/utils.py
@@ -239,13 +239,12 @@
 	if exact_match:
 		data = get_product_info_for_website(exact_match[0])
 		product_info = data.product_info
+		product_info["allow_items_not_in_stock"] = cint(data.cart_settings.allow_items_not_in_stock)
 		if not data.cart_settings.show_price:
 			product_info = None
 	else:
 		product_info = None
 
-	product_info["allow_items_not_in_stock"] = cint(data.cart_settings.allow_items_not_in_stock)
-
 	return {
 		'next_attribute': next_attribute,
 		'valid_options_for_attributes': valid_options_for_attributes,
diff --git a/erpnext/portal/utils.py b/erpnext/portal/utils.py
index 56e4fcd..d6d4469 100644
--- a/erpnext/portal/utils.py
+++ b/erpnext/portal/utils.py
@@ -88,21 +88,30 @@
 	party.flags.ignore_mandatory = True
 	party.insert(ignore_permissions=True)
 
+	alternate_doctype = "Customer" if doctype == "Supplier" else "Supplier"
+
+	if party_exists(alternate_doctype, user):
+		# if user is both customer and supplier, alter fullname to avoid contact name duplication
+		fullname +=  "-" + doctype
+
+	create_party_contact(doctype, fullname, user, party.name)
+
+	return party
+
+def create_party_contact(doctype, fullname, user, party_name):
 	contact = frappe.new_doc("Contact")
 	contact.update({
 		"first_name": fullname,
 		"email_id": user
 	})
-	contact.append('links', dict(link_doctype=doctype, link_name=party.name))
+	contact.append('links', dict(link_doctype=doctype, link_name=party_name))
+	contact.append('email_ids', dict(email_id=user))
 	contact.flags.ignore_mandatory = True
 	contact.insert(ignore_permissions=True)
 
-	return party
-
-
 def party_exists(doctype, user):
+	# check if contact exists against party and if it is linked to the doctype
 	contact_name = frappe.db.get_value("Contact", {"email_id": user})
-
 	if contact_name:
 		contact = frappe.get_doc('Contact', contact_name)
 		doctypes = [d.link_doctype for d in contact.links]
diff --git a/erpnext/projects/dashboard_chart/project_summary/project_summary.json b/erpnext/projects/dashboard_chart/project_summary/project_summary.json
new file mode 100644
index 0000000..157ee1b
--- /dev/null
+++ b/erpnext/projects/dashboard_chart/project_summary/project_summary.json
@@ -0,0 +1,24 @@
+{
+ "chart_name": "Project Summary",
+ "chart_type": "Report",
+ "creation": "2020-07-20 20:17:16.363681",
+ "custom_options": "{\"type\": \"bar\", \"colors\": [\"#fc4f51\", \"#78d6ff\", \"#7575ff\"], \"axisOptions\": { \"shortenYAxisNumbers\": 1}, \"barOptions\": { \"stacked\": 1 }}",
+ "docstatus": 0,
+ "doctype": "Dashboard Chart",
+ "dynamic_filters_json": "{\"company\":\"frappe.defaults.get_user_default(\\\"Company\\\")\"}",
+ "filters_json": "{\"status\":\"Open\"}",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "modified": "2020-07-22 17:16:39.627076",
+ "modified_by": "Administrator",
+ "module": "Projects",
+ "name": "Project Summary",
+ "number_of_groups": 0,
+ "owner": "Administrator",
+ "report_name": "Project Summary",
+ "timeseries": 0,
+ "type": "Bar",
+ "use_report_chart": 1,
+ "y_axis": []
+}
\ No newline at end of file
diff --git a/erpnext/projects/dashboard_fixtures.py b/erpnext/projects/dashboard_fixtures.py
deleted file mode 100644
index d89ffe9..0000000
--- a/erpnext/projects/dashboard_fixtures.py
+++ /dev/null
@@ -1,50 +0,0 @@
-# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-import frappe
-import json
-from frappe import _
-
-def get_company_for_dashboards():
-	company = frappe.defaults.get_defaults().company
-	if company:
-		return company
-	else:
-		company_list = frappe.get_list("Company")
-		if company_list:
-			return company_list[0].name
-	return None
-
-def get_data():
-	return frappe._dict({
-		"dashboards": get_dashboards(),
-		"charts": get_charts(),
-	})
-
-def get_dashboards():
-	return [{
-		"doctype": "Dashboard",
-		"name": "Project",
-		"dashboard_name": "Project",
-		"charts": [
-			{ "chart": "Project Summary", "width": "Full" }
-		]
-	}]
-
-def get_charts():
-	company = frappe.get_doc("Company", get_company_for_dashboards())
-
-	return [
-		{
-			'doctype': 'Dashboard Chart',
-			'name': 'Project Summary',
-			'chart_name': _('Project Summary'),
-			'chart_type': 'Report',
-			'report_name': 'Project Summary',
-			'is_public': 1,
-			'is_custom': 1,
-			'filters_json': json.dumps({"company": company.name, "status": "Open"}),
-			'type': 'Bar',
-			'custom_options': '{"type": "bar", "colors": ["#fc4f51", "#78d6ff", "#7575ff"], "axisOptions": { "shortenYAxisNumbers": 1}, "barOptions": { "stacked": 1 }}',
-		}
-	]
\ No newline at end of file
diff --git a/erpnext/projects/desk_page/projects/projects.json b/erpnext/projects/desk_page/projects/projects.json
index d91fe53..e24cf30 100644
--- a/erpnext/projects/desk_page/projects/projects.json
+++ b/erpnext/projects/desk_page/projects/projects.json
@@ -68,7 +68,7 @@
    "type": "Report"
   },
   {
-   "label": "Project Dashboard",
+   "label": "Dashboard",
    "link_to": "Project",
    "type": "Dashboard"
   }
diff --git a/erpnext/projects/doctype/project/project.py b/erpnext/projects/doctype/project/project.py
index afdb5b7..6350f86 100644
--- a/erpnext/projects/doctype/project/project.py
+++ b/erpnext/projects/doctype/project/project.py
@@ -238,6 +238,7 @@
 		"row_template": "templates/includes/projects/project_row.html"
 	}
 
+@frappe.whitelist()
 def get_users_for_project(doctype, txt, searchfield, start, page_len, filters):
 	conditions = []
 	return frappe.db.sql("""select name, concat_ws(' ', first_name, middle_name, last_name)
@@ -471,7 +472,7 @@
 	from frappe.desk.doctype.kanban_board.kanban_board import quick_kanban_board
 
 	if not frappe.db.exists('Kanban Board', project):
-		quick_kanban_board('Task', project, 'status')
+		quick_kanban_board('Task', project, 'status', project)
 
 	return True
 
diff --git a/erpnext/projects/doctype/project/test_project.py b/erpnext/projects/doctype/project/test_project.py
index 06c62b6..0c4f6f1 100644
--- a/erpnext/projects/doctype/project/test_project.py
+++ b/erpnext/projects/doctype/project/test_project.py
@@ -7,7 +7,7 @@
 test_records = frappe.get_test_records('Project')
 test_ignore = ["Sales Order"]
 
-from erpnext.projects.doctype.project_template.test_project_template import get_project_template
+from erpnext.projects.doctype.project_template.test_project_template import get_project_template, make_project_template
 from erpnext.projects.doctype.project.project import set_project_status
 
 from frappe.utils import getdate
@@ -43,4 +43,24 @@
 		expected_start_date = '2019-01-01'
 	)).insert()
 
+	return project
+
+def make_project(args):
+	args = frappe._dict(args)
+	if args.project_template_name:
+		template = make_project_template(args.project_template_name)
+	else:
+		template = get_project_template()
+
+	project = frappe.get_doc(dict(
+		doctype = 'Project',
+		project_name = args.project_name,
+		status = 'Open',
+		project_template = template.name,
+		expected_start_date = args.start_date
+	))
+
+	if not frappe.db.exists("Project", args.project_name):
+		project.insert()
+
 	return project
\ No newline at end of file
diff --git a/erpnext/projects/doctype/project_template/test_project_template.py b/erpnext/projects/doctype/project_template/test_project_template.py
index efcb2ea..2c5831a 100644
--- a/erpnext/projects/doctype/project_template/test_project_template.py
+++ b/erpnext/projects/doctype/project_template/test_project_template.py
@@ -26,4 +26,23 @@
 			]
 		)).insert()
 
-	return frappe.get_doc('Project Template', 'Test Project Template')
\ No newline at end of file
+	return frappe.get_doc('Project Template', 'Test Project Template')
+
+def make_project_template(project_template_name, project_tasks=[]):
+	if not frappe.db.exists('Project Template', project_template_name):
+		frappe.get_doc(dict(
+			doctype = 'Project Template',
+			name = project_template_name,
+			tasks = project_tasks or [
+				dict(subject='Task 1', description='Task 1 description',
+					start=0, duration=3),
+				dict(subject='Task 2', description='Task 2 description',
+					start=0, duration=2),
+				dict(subject='Task 3', description='Task 3 description',
+					start=2, duration=4),
+				dict(subject='Task 4', description='Task 4 description',
+					start=3, duration=2),
+			]
+		)).insert()
+
+	return frappe.get_doc('Project Template', project_template_name)
\ No newline at end of file
diff --git a/erpnext/projects/doctype/task/task.js b/erpnext/projects/doctype/task/task.js
index 5719276..8c6a9cf 100644
--- a/erpnext/projects/doctype/task/task.js
+++ b/erpnext/projects/doctype/task/task.js
@@ -3,55 +3,42 @@
 
 frappe.provide("erpnext.projects");
 
-cur_frm.add_fetch("project", "company", "company");
-
 frappe.ui.form.on("Task", {
-	onload: function(frm) {
-		frm.set_query("task", "depends_on", function() {
-			var filters = {
+	setup: function (frm) {
+		frm.set_query("project", function () {
+			return {
+				query: "erpnext.projects.doctype.task.task.get_project"
+			}
+		});
+
+		frm.make_methods = {
+			'Timesheet': () => frappe.model.open_mapped_doc({
+				method: 'erpnext.projects.doctype.task.task.make_timesheet',
+				frm: frm
+			})
+		}
+	},
+
+	onload: function (frm) {
+		frm.set_query("task", "depends_on", function () {
+			let filters = {
 				name: ["!=", frm.doc.name]
 			};
-			if(frm.doc.project) filters["project"] = frm.doc.project;
+			if (frm.doc.project) filters["project"] = frm.doc.project;
 			return {
 				filters: filters
 			};
 		})
-	},
 
-	refresh: function(frm) {
-		frm.fields_dict['parent_task'].get_query = function () {
+		frm.set_query("parent_task", function () {
+			let filters = {
+				"is_group": 1
+			};
+			if (frm.doc.project) filters["project"] = frm.doc.project;
 			return {
-				filters: {
-					"is_group": 1,
-				}
+				filters: filters
 			}
-		}
-
-		if (!frm.doc.is_group) {
-			if (!frm.is_new()) {
-				if (frappe.model.can_read("Timesheet")) {
-					frm.add_custom_button(__("Timesheet"), () => {
-						frappe.route_options = { "project": frm.doc.project, "task": frm.doc.name }
-						frappe.set_route("List", "Timesheet");
-					}, __("View"), true);
-				}
-
-				if (frappe.model.can_read("Expense Claim")) {
-					frm.add_custom_button(__("Expense Claims"), () => {
-						frappe.route_options = { "project": frm.doc.project, "task": frm.doc.name };
-						frappe.set_route("List", "Expense Claim");
-					}, __("View"), true);
-				}
-			}
-		}
-	},
-
-	setup: function(frm) {
-		frm.fields_dict.project.get_query = function() {
-			return {
-				query: "erpnext.projects.doctype.task.task.get_project"
-			}
-		};
+		});
 	},
 
 	is_group: function (frm) {
@@ -69,12 +56,8 @@
 		})
 	},
 
-	validate: function(frm) {
+	validate: function (frm) {
 		frm.doc.project && frappe.model.remove_from_locals("Project",
 			frm.doc.project);
-	},
-
+	}
 });
-
-cur_frm.add_fetch('task', 'subject', 'subject');
-cur_frm.add_fetch('task', 'project', 'project');
diff --git a/erpnext/projects/doctype/task/task.json b/erpnext/projects/doctype/task/task.json
index f4b3d3e..27f1a71 100644
--- a/erpnext/projects/doctype/task/task.json
+++ b/erpnext/projects/doctype/task/task.json
@@ -183,7 +183,8 @@
   {
    "fieldname": "progress",
    "fieldtype": "Percent",
-   "label": "% Progress"
+   "label": "% Progress",
+   "no_copy": 1
   },
   {
    "default": "0",
@@ -324,6 +325,7 @@
    "options": "Department"
   },
   {
+   "fetch_from": "project.company",
    "fieldname": "company",
    "fieldtype": "Link",
    "label": "Company",
@@ -356,6 +358,7 @@
    "fieldname": "completed_by",
    "fieldtype": "Link",
    "label": "Completed By",
+   "no_copy": 1,
    "options": "User"
   }
  ],
@@ -364,7 +367,7 @@
  "is_tree": 1,
  "links": [],
  "max_attachments": 5,
- "modified": "2020-03-18 18:08:44.153211",
+ "modified": "2020-07-03 12:36:04.960457",
  "modified_by": "Administrator",
  "module": "Projects",
  "name": "Task",
diff --git a/erpnext/projects/doctype/task/task.py b/erpnext/projects/doctype/task/task.py
index 1cb2c50..4bdda68 100755
--- a/erpnext/projects/doctype/task/task.py
+++ b/erpnext/projects/doctype/task/task.py
@@ -7,10 +7,11 @@
 
 import frappe
 from frappe import _, throw
-from frappe.utils import add_days, cstr, date_diff, get_link_to_form, getdate, today
+from frappe.desk.form.assign_to import clear, close_all_assignments
+from frappe.model.mapper import get_mapped_doc
+from frappe.utils import add_days, cstr, date_diff, get_link_to_form, getdate, today, flt
 from frappe.utils.nestedset import NestedSet
-from frappe.desk.form.assign_to import close_all_assignments, clear
-from frappe.utils import date_diff
+
 
 class CircularReferenceError(frappe.ValidationError): pass
 class EndDateCannotBeGreaterThanProjectEndDateError(frappe.ValidationError): pass
@@ -62,10 +63,10 @@
 			close_all_assignments(self.doctype, self.name)
 
 	def validate_progress(self):
-		if (self.progress or 0) > 100:
+		if flt(self.progress or 0) > 100:
 			frappe.throw(_("Progress % for a task cannot be more than 100."))
 
-		if self.progress == 100:
+		if flt(self.progress) == 100:
 			self.status = 'Completed'
 
 		if self.status == 'Completed':
@@ -188,6 +189,7 @@
 	return child_tasks
 
 
+@frappe.whitelist()
 def get_project(doctype, txt, searchfield, start, page_len, filters):
 	from erpnext.controllers.queries import get_match_cond
 	return frappe.db.sql(""" select name from `tabProject`
@@ -219,6 +221,26 @@
 				continue
 		frappe.get_doc("Task", task.name).update_status()
 
+
+@frappe.whitelist()
+def make_timesheet(source_name, target_doc=None, ignore_permissions=False):
+	def set_missing_values(source, target):
+		target.append("time_logs", {
+			"hours": source.actual_time,
+			"completed": source.status == "Completed",
+			"project": source.project,
+			"task": source.name
+		})
+
+	doclist = get_mapped_doc("Task", source_name, {
+			"Task": {
+				"doctype": "Timesheet"
+			}
+		}, target_doc, postprocess=set_missing_values, ignore_permissions=ignore_permissions)
+
+	return doclist
+
+
 @frappe.whitelist()
 def get_children(doctype, parent, task=None, project=None, is_root=False):
 
diff --git a/erpnext/projects/doctype/timesheet/test_timesheet.py b/erpnext/projects/doctype/timesheet/test_timesheet.py
index 03b67b1..a5ce44d 100644
--- a/erpnext/projects/doctype/timesheet/test_timesheet.py
+++ b/erpnext/projects/doctype/timesheet/test_timesheet.py
@@ -140,52 +140,6 @@
 		settings.ignore_employee_time_overlap = initial_setting
 		settings.save()
 
-	def test_timesheet_std_working_hours(self):
-		emp = make_employee("test_employee_6@salary.com")
-
-		company = frappe.get_doc('Company', "_Test Company")
-		company.standard_working_hours = 8
-		company.save()
-
-		timesheet = frappe.new_doc("Timesheet")
-		timesheet.employee = emp
-		timesheet.company = '_Test Company'
-		timesheet.append(
-			'time_logs',
-			{
-				"activity_type": "_Test Activity Type",
-				"from_time": now_datetime(),
-				"to_time": now_datetime() + datetime.timedelta(days= 4)
-			}
-		)
-		timesheet.save()
-
-		ts = frappe.get_doc('Timesheet', timesheet.name)
-		self.assertEqual(ts.total_hours, 32)
-		ts.submit()
-		ts.cancel()
-
-		company = frappe.get_doc('Company', "_Test Company")
-		company.standard_working_hours = 0
-		company.save()
-
-		timesheet = frappe.new_doc("Timesheet")
-		timesheet.employee = emp
-		timesheet.company = '_Test Company'
-		timesheet.append(
-			'time_logs',
-			{
-				"activity_type": "_Test Activity Type",
-				"from_time": now_datetime(),
-				"to_time": now_datetime() + datetime.timedelta(days= 4)
-			}
-		)
-		timesheet.save()
-
-		ts = frappe.get_doc('Timesheet', timesheet.name)
-		self.assertEqual(ts.total_hours, 96)
-		ts.submit()
-		ts.cancel()
 
 def make_salary_structure_for_timesheet(employee):
 	salary_structure_name = "Timesheet Salary Structure Test"
diff --git a/erpnext/projects/doctype/timesheet/timesheet.js b/erpnext/projects/doctype/timesheet/timesheet.js
index defc18b..5de2930 100644
--- a/erpnext/projects/doctype/timesheet/timesheet.js
+++ b/erpnext/projects/doctype/timesheet/timesheet.js
@@ -162,19 +162,11 @@
 
 	to_time: function(frm, cdt, cdn) {
 		var child = locals[cdt][cdn];
-		var time_diff = (moment(child.to_time).diff(moment(child.from_time),"seconds")) / ( 60 * 60 * 24);
-		var std_working_hours = 0;
 
 		if(frm._setting_hours) return;
 
 		var hours = moment(child.to_time).diff(moment(child.from_time), "seconds") / 3600;
-		std_working_hours = time_diff * frappe.working_hours;
-
-		if (std_working_hours < hours && std_working_hours > 0) {
-			frappe.model.set_value(cdt, cdn, "hours", std_working_hours);
-		} else {
-			frappe.model.set_value(cdt, cdn, "hours", hours);
-		}
+		frappe.model.set_value(cdt, cdn, "hours", hours);
 	},
 
 	time_logs_add: function(frm) {
@@ -236,23 +228,12 @@
 
 	let d = moment(child.from_time);
 	if(child.hours) {
-		var time_diff = (moment(child.to_time).diff(moment(child.from_time),"seconds")) / (60 * 60 * 24);
-		var std_working_hours = 0;
-		var hours = moment(child.to_time).diff(moment(child.from_time), "seconds") / 3600;
-
-		std_working_hours = time_diff * frappe.working_hours;
-
-		if (std_working_hours < hours && std_working_hours > 0) {
-			frappe.model.set_value(cdt, cdn, "hours", std_working_hours);
-			frappe.model.set_value(cdt, cdn, "to_time", d.add(hours, "hours").format(frappe.defaultDatetimeFormat));
-		} else {
-			d.add(child.hours, "hours");
-			frm._setting_hours = true;
-			frappe.model.set_value(cdt, cdn, "to_time",
-				d.format(frappe.defaultDatetimeFormat)).then(() => {
-				frm._setting_hours = false;
-			});
-		}
+		d.add(child.hours, "hours");
+		frm._setting_hours = true;
+		frappe.model.set_value(cdt, cdn, "to_time",
+			d.format(frappe.defaultDatetimeFormat)).then(() => {
+			frm._setting_hours = false;
+		});
 	}
 };
 
diff --git a/erpnext/projects/doctype/timesheet/timesheet.py b/erpnext/projects/doctype/timesheet/timesheet.py
index e908216..7fe22be 100644
--- a/erpnext/projects/doctype/timesheet/timesheet.py
+++ b/erpnext/projects/doctype/timesheet/timesheet.py
@@ -24,7 +24,6 @@
 		self.set_status()
 		self.validate_dates()
 		self.validate_time_logs()
-		self.calculate_std_hours()
 		self.update_cost()
 		self.calculate_total_amounts()
 		self.calculate_percentage_billed()
@@ -91,17 +90,6 @@
 				self.start_date = getdate(start_date)
 				self.end_date = getdate(end_date)
 
-	def calculate_std_hours(self):
-		std_working_hours = frappe.get_value("Company", self.company, 'standard_working_hours')
-
-		for time in self.time_logs:
-			if time.from_time and time.to_time:
-				if flt(std_working_hours) and date_diff(time.to_time, time.from_time):
-					time.hours = flt(std_working_hours) * date_diff(time.to_time, time.from_time)
-				else:
-					if not time.hours:
-						time.hours = time_diff_in_hours(time.to_time, time.from_time)
-
 	def before_cancel(self):
 		self.set_status()
 
diff --git a/erpnext/projects/doctype/timesheet/timesheet_dashboard.py b/erpnext/projects/doctype/timesheet/timesheet_dashboard.py
new file mode 100644
index 0000000..acff97a
--- /dev/null
+++ b/erpnext/projects/doctype/timesheet/timesheet_dashboard.py
@@ -0,0 +1,13 @@
+from __future__ import unicode_literals
+from frappe import _
+
+def get_data():
+	return {
+		'fieldname': 'time_sheet',
+		'transactions': [
+			{
+				'label': _('References'),
+				'items': ['Sales Invoice', 'Salary Slip']
+			}
+		]
+	}
\ No newline at end of file
diff --git a/erpnext/projects/projects_dashboard/project/project.json b/erpnext/projects/projects_dashboard/project/project.json
new file mode 100644
index 0000000..f7824ce
--- /dev/null
+++ b/erpnext/projects/projects_dashboard/project/project.json
@@ -0,0 +1,21 @@
+{
+ "cards": [],
+ "charts": [
+  {
+   "chart": "Project Summary",
+   "width": "Full"
+  }
+ ],
+ "creation": "2020-07-20 20:17:16.397373",
+ "dashboard_name": "Project",
+ "docstatus": 0,
+ "doctype": "Dashboard",
+ "idx": 0,
+ "is_default": 0,
+ "is_standard": 1,
+ "modified": "2020-07-22 17:17:03.780625",
+ "modified_by": "Administrator",
+ "module": "Projects",
+ "name": "Project",
+ "owner": "Administrator"
+}
\ No newline at end of file
diff --git a/erpnext/public/css/pos.css b/erpnext/public/css/pos.css
index 613a5ff..e80e3ed 100644
--- a/erpnext/public/css/pos.css
+++ b/erpnext/public/css/pos.css
@@ -1,179 +1,216 @@
-[data-route="point-of-sale"] .layout-main-section-wrapper {
-  margin-bottom: 0;
-}
-[data-route="point-of-sale"] .pos-items-wrapper {
-  max-height: calc(100vh - 210px);
-}
-.pos {
-  padding: 15px;
-}
-.list-item {
-  min-height: 40px;
-  height: auto;
-}
-.cart-container {
-  padding: 0 15px;
-  display: inline-block;
-  width: 39%;
-  vertical-align: top;
-}
-.item-container {
-  padding: 0 15px;
-  display: inline-block;
-  width: 60%;
-  vertical-align: top;
-}
-.search-field {
-  width: 60%;
-}
-.search-field input::placeholder {
-  font-size: 12px;
-}
-.item-group-field {
-  width: 40%;
-  margin-left: 15px;
-}
-.cart-wrapper {
-  margin-bottom: 12px;
-}
-.cart-wrapper .list-item__content:not(:first-child) {
-  justify-content: flex-end;
-}
-.cart-wrapper .list-item--head .list-item__content:nth-child(2) {
-  flex: 1.5;
-}
-.cart-items {
-  height: 150px;
-  overflow: auto;
-}
-.cart-items .list-item.current-item {
-  background-color: #fffce7;
-}
-.cart-items .list-item.current-item.qty input {
-  border: 1px solid #5E64FF;
-  font-weight: bold;
-}
-.cart-items .list-item.current-item.disc .discount {
-  font-weight: bold;
-}
-.cart-items .list-item.current-item.rate .rate {
-  font-weight: bold;
-}
-.cart-items .list-item .quantity {
-  flex: 1.5;
-}
-.cart-items input {
-  text-align: right;
-  height: 22px;
-  font-size: 12px;
-}
-.fields {
-  display: flex;
-}
-.pos-items-wrapper {
-  max-height: 480px;
-  overflow-y: auto;
-}
-.pos-items {
-  overflow: hidden;
-}
-.pos-item-wrapper {
-  display: flex;
-  flex-direction: column;
-  position: relative;
-  width: 25%;
-}
-.image-view-container {
-  display: block;
-}
-.image-view-container .image-field {
-  height: auto;
-}
-.empty-state {
-  height: 100%;
-  position: relative;
-}
-.empty-state span {
-  position: absolute;
-  color: #8D99A6;
-  font-size: 12px;
-  top: 50%;
-  left: 50%;
-  transform: translate(-50%, -50%);
-}
-@keyframes yellow-fade {
-  0% {
-    background-color: #fffce7;
-  }
-  100% {
-    background-color: transparent;
-  }
-}
-.highlight {
-  animation: yellow-fade 1s ease-in 1;
-}
-input[type=number]::-webkit-inner-spin-button,
-input[type=number]::-webkit-outer-spin-button {
-  -webkit-appearance: none;
-  margin: 0;
-}
-.number-pad {
-  border-collapse: collapse;
-  cursor: pointer;
-  display: table;
-}
-.num-row {
-  display: table-row;
-}
-.num-col {
-  display: table-cell;
-  border: 1px solid #d1d8dd;
-}
-.num-col > div {
-  width: 50px;
-  height: 50px;
-  text-align: center;
-  line-height: 50px;
-}
-.num-col.active {
-  background-color: #fffce7;
-}
-.num-col.brand-primary {
-  background-color: #5E64FF;
-  color: #ffffff;
-}
-.discount-amount .discount-inputs {
-  display: flex;
-  flex-direction: column;
-  padding: 15px 0;
-}
-.discount-amount input:first-child {
-  margin-bottom: 10px;
-}
-.taxes-and-totals {
-  border-top: 1px solid #d1d8dd;
-}
-.taxes-and-totals .taxes {
-  display: flex;
-  flex-direction: column;
-  padding: 15px 0;
-  align-items: flex-end;
-}
-.taxes-and-totals .taxes > div:first-child {
-  margin-bottom: 10px;
-}
-.grand-total {
-  border-top: 1px solid #d1d8dd;
-}
-.grand-total .list-item {
-  height: 60px;
-}
-.grand-total .grand-total-value {
-  font-size: 18px;
-}
-.rounded-total-value {
-  font-size: 18px;
-}
-.quantity-total {
-  font-size: 18px;
-}
+[data-route="point-of-sale"] .layout-main-section { border: none;  font-size: 12px; }
+[data-route="point-of-sale"] .layout-main-section-wrapper { margin-bottom: 0; }
+[data-route="point-of-sale"] .pos-items-wrapper { max-height: calc(100vh - 210px); }
+:root { --border-color: #d1d8dd;  --text-color: #8d99a6;  --primary: #5e64ff; }
+[data-route="point-of-sale"] .flex { display: flex; }
+[data-route="point-of-sale"] .grid { display: grid; }
+[data-route="point-of-sale"] .absolute { position: absolute; }
+[data-route="point-of-sale"] .relative { position: relative; }
+[data-route="point-of-sale"] .abs-center { top: 50%; left: 50%; transform: translate(-50%, -50%); }
+[data-route="point-of-sale"] .inline { display: inline; }
+[data-route="point-of-sale"] .float-right { float: right; }
+[data-route="point-of-sale"] .grid-cols-1 { grid-template-columns: repeat(1, minmax(0, 1fr)); }
+[data-route="point-of-sale"] .grid-cols-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
+[data-route="point-of-sale"] .grid-cols-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
+[data-route="point-of-sale"] .grid-cols-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
+[data-route="point-of-sale"] .grid-cols-5 { grid-template-columns: repeat(5, minmax(0, 1fr)); }
+[data-route="point-of-sale"] .grid-cols-10 { grid-template-columns: repeat(10, minmax(0, 1fr)); }
+[data-route="point-of-sale"] .gap-2 { grid-gap: 0.5rem;  gap: 0.5rem; }
+[data-route="point-of-sale"] .gap-4 { grid-gap: 1rem;  gap: 1rem; }
+[data-route="point-of-sale"] .gap-6 { grid-gap: 1.25rem;  gap: 1.25rem; }
+[data-route="point-of-sale"] .gap-8 { grid-gap: 1.5rem;  gap: 1.5rem; }
+[data-route="point-of-sale"] .row-gap-2 { grid-row-gap: 0.5rem;  row-gap: 0.5rem; }
+[data-route="point-of-sale"] .col-gap-4 { grid-column-gap: 1rem;  column-gap: 1rem; }
+[data-route="point-of-sale"] .col-span-2 { grid-column: span 2 / span 2; }
+[data-route="point-of-sale"] .col-span-3 { grid-column: span 3 / span 3; }
+[data-route="point-of-sale"] .col-span-4 { grid-column: span 4 / span 4; }
+[data-route="point-of-sale"] .col-span-6 { grid-column: span 6 / span 6; }
+[data-route="point-of-sale"] .col-span-10 { grid-column: span 10 / span 10; }
+[data-route="point-of-sale"] .row-span-2 { grid-row: span 2 / span 2; }
+[data-route="point-of-sale"] .grid-auto-row { grid-auto-rows: 5.5rem; }
+[data-route="point-of-sale"] .d-none { display: none; }
+[data-route="point-of-sale"] .flex-wrap { flex-wrap: wrap; }
+[data-route="point-of-sale"] .flex-row { flex-direction: row; }
+[data-route="point-of-sale"] .flex-col { flex-direction: column; }
+[data-route="point-of-sale"] .flex-row-rev { flex-direction: row-reverse; }
+[data-route="point-of-sale"] .flex-col-rev { flex-direction: column-reverse; }
+[data-route="point-of-sale"] .flex-1 { flex: 1 1 0%; }
+[data-route="point-of-sale"] .items-center { align-items: center; }
+[data-route="point-of-sale"] .items-end { align-items: flex-end; }
+[data-route="point-of-sale"] .f-grow-1 { flex-grow: 1; }
+[data-route="point-of-sale"] .f-grow-2 { flex-grow: 2; }
+[data-route="point-of-sale"] .f-grow-3 { flex-grow: 3; }
+[data-route="point-of-sale"] .f-grow-4 { flex-grow: 4; }
+[data-route="point-of-sale"] .f-shrink-0 { flex-shrink: 0; }
+[data-route="point-of-sale"] .f-shrink-1 { flex-shrink: 1; }
+[data-route="point-of-sale"] .f-shrink-2 { flex-shrink: 2; }
+[data-route="point-of-sale"] .f-shrink-3 { flex-shrink: 3; }
+[data-route="point-of-sale"] .shadow { box-shadow: 0 0px 3px 0 rgba(0, 0, 0, 0.2), 0 1px 2px 0 rgba(0, 0, 0, 0.06); }
+[data-route="point-of-sale"] .shadow-sm { box-shadow: 0 0.5px 3px 0 rgba(0, 0, 0, 0.125); }
+[data-route="point-of-sale"] .shadow-inner { box-shadow: inset 0 2px 4px 0 rgba(0, 0, 0, 0.1); }
+[data-route="point-of-sale"] .rounded { border-radius: 0.3rem; }
+[data-route="point-of-sale"] .rounded-b { border-bottom-left-radius: 0.3rem;  border-bottom-right-radius: 0.3rem; }
+[data-route="point-of-sale"] .p-8 { padding: 2rem; }
+[data-route="point-of-sale"] .p-16 { padding: 4rem; }
+[data-route="point-of-sale"] .p-32 { padding: 8rem; }
+[data-route="point-of-sale"] .p-6 { padding: 1.5rem; }
+[data-route="point-of-sale"] .p-4 { padding: 1rem; }
+[data-route="point-of-sale"] .p-3 { padding: 0.75rem; }
+[data-route="point-of-sale"] .p-2 { padding: 0.5rem; }
+[data-route="point-of-sale"] .m-8 { margin: 2rem; }
+[data-route="point-of-sale"] .p-1 { padding: 0.25rem; }
+[data-route="point-of-sale"] .pr-0 { padding-right: 0rem; }
+[data-route="point-of-sale"] .pl-0 { padding-left: 0rem; }
+[data-route="point-of-sale"] .pt-0 { padding-top: 0rem; }
+[data-route="point-of-sale"] .pb-0 { padding-bottom: 0rem; }
+[data-route="point-of-sale"] .mr-0 { margin-right: 0rem; }
+[data-route="point-of-sale"] .ml-0 { margin-left: 0rem; }
+[data-route="point-of-sale"] .mt-0 { margin-top: 0rem; }
+[data-route="point-of-sale"] .mb-0 { margin-bottom: 0rem; }
+[data-route="point-of-sale"] .pr-2 { padding-right: 0.5rem; }
+[data-route="point-of-sale"] .pl-2 { padding-left: 0.5rem; }
+[data-route="point-of-sale"] .pt-2 { padding-top: 0.5rem; }
+[data-route="point-of-sale"] .pb-2 { padding-bottom: 0.5rem; }
+[data-route="point-of-sale"] .pr-3 { padding-right: 0.75rem; }
+[data-route="point-of-sale"] .pl-3 { padding-left: 0.75rem; }
+[data-route="point-of-sale"] .pt-3 { padding-top: 0.75rem; }
+[data-route="point-of-sale"] .pb-3 { padding-bottom: 0.75rem; }
+[data-route="point-of-sale"] .pr-4 { padding-right: 1rem; }
+[data-route="point-of-sale"] .pl-4 { padding-left: 1rem; }
+[data-route="point-of-sale"] .pt-4 { padding-top: 1rem; }
+[data-route="point-of-sale"] .pb-4 { padding-bottom: 1rem; }
+[data-route="point-of-sale"] .mr-4 { margin-right: 1rem; }
+[data-route="point-of-sale"] .ml-4 { margin-left: 1rem; }
+[data-route="point-of-sale"] .mt-4 { margin-top: 1rem; }
+[data-route="point-of-sale"] .mb-4 { margin-bottom: 1rem; }
+[data-route="point-of-sale"] .mr-2 { margin-right: 0.5rem; }
+[data-route="point-of-sale"] .ml-2 { margin-left: 0.5rem; }
+[data-route="point-of-sale"] .mt-2 { margin-top: 0.5rem; }
+[data-route="point-of-sale"] .mb-2 { margin-bottom: 0.5rem; }
+[data-route="point-of-sale"] .mr-1 { margin-right: 0.25rem; }
+[data-route="point-of-sale"] .ml-1 { margin-left: 0.25rem; }
+[data-route="point-of-sale"] .mt-1 { margin-top: 0.25rem; }
+[data-route="point-of-sale"] .mb-1 { margin-bottom: 0.25rem; }
+[data-route="point-of-sale"] .mr-auto { margin-right: auto; }
+[data-route="point-of-sale"] .ml-auto { margin-left: auto; }
+[data-route="point-of-sale"] .mt-auto { margin-top: auto; }
+[data-route="point-of-sale"] .mb-auto { margin-bottom: auto; }
+[data-route="point-of-sale"] .pr-6 { padding-right: 1.5rem; }
+[data-route="point-of-sale"] .pl-6 { padding-left: 1.5rem; }
+[data-route="point-of-sale"] .pt-6 { padding-top: 1.5rem; }
+[data-route="point-of-sale"] .pb-6 { padding-bottom: 1.5rem; }
+[data-route="point-of-sale"] .mr-6 { margin-right: 1.5rem; }
+[data-route="point-of-sale"] .ml-6 { margin-left: 1.5rem; }
+[data-route="point-of-sale"] .mt-6 { margin-top: 1.5rem; }
+[data-route="point-of-sale"] .mb-6 { margin-bottom: 1.5rem; }
+[data-route="point-of-sale"] .mr-8 { margin-right: 2rem; }
+[data-route="point-of-sale"] .ml-8 { margin-left: 2rem; }
+[data-route="point-of-sale"] .mt-8 { margin-top: 2rem; }
+[data-route="point-of-sale"] .mb-8 { margin-bottom: 2rem; }
+[data-route="point-of-sale"] .pr-8 { padding-right: 2rem; }
+[data-route="point-of-sale"] .pl-8 { padding-left: 2rem; }
+[data-route="point-of-sale"] .pt-8 { padding-top: 2rem; }
+[data-route="point-of-sale"] .pb-8 { padding-bottom: 2rem; }
+[data-route="point-of-sale"] .pr-16 { padding-right: 4rem; }
+[data-route="point-of-sale"] .pl-16 { padding-left: 4rem; }
+[data-route="point-of-sale"] .pt-16 { padding-top: 4rem; }
+[data-route="point-of-sale"] .pb-16 { padding-bottom: 4rem; }
+[data-route="point-of-sale"] .w-full { width: 100%; }
+[data-route="point-of-sale"] .h-full { height: 100%; }
+[data-route="point-of-sale"] .w-quarter { width: 25%; }
+[data-route="point-of-sale"] .w-half { width: 50%; }
+[data-route="point-of-sale"] .w-66 { width: 66.66%; }
+[data-route="point-of-sale"] .w-33 { width: 33.33%; }
+[data-route="point-of-sale"] .w-60 { width: 60%; }
+[data-route="point-of-sale"] .w-40 { width: 40%; }
+[data-route="point-of-sale"] .w-fit { width: fit-content; }
+[data-route="point-of-sale"] .w-6 { width: 2rem; }
+[data-route="point-of-sale"] .h-6 { min-height: 2rem; height: 2rem; }
+[data-route="point-of-sale"] .w-8 { width: 2.5rem; }
+[data-route="point-of-sale"] .h-8 { min-height: 2.5rem; height: 2.5rem; }
+[data-route="point-of-sale"] .w-10 { width: 3rem; }
+[data-route="point-of-sale"] .h-10 { min-height:3rem; height: 3rem; }
+[data-route="point-of-sale"] .h-12 { min-height: 3.3rem; height: 3.3rem; }
+[data-route="point-of-sale"] .w-12 { width: 3.3rem; }
+[data-route="point-of-sale"] .h-14 { min-height: 4.2rem; height: 4.2rem; }
+[data-route="point-of-sale"] .h-16 { min-height: 4.6rem; height: 4.6rem; }
+[data-route="point-of-sale"] .h-18 { min-height: 5rem; height: 5rem; }
+[data-route="point-of-sale"] .w-18 { width: 5.4rem; }
+[data-route="point-of-sale"] .w-24 { width: 7.2rem; }
+[data-route="point-of-sale"] .w-26 { width: 8.4rem; }
+[data-route="point-of-sale"] .h-24 { min-height: 7.2rem; height: 7.2rem; }
+[data-route="point-of-sale"] .h-32 { min-height: 9.6rem; height: 9.6rem; }
+[data-route="point-of-sale"] .w-46 { width: 15rem; }
+[data-route="point-of-sale"] .h-46 { min-height:15rem; height: 15rem; }
+[data-route="point-of-sale"] .h-100 { height: 100vh; }
+[data-route="point-of-sale"] .mx-h-70 { max-height: 67rem; }
+[data-route="point-of-sale"] .border-grey-300 { border-color: #e2e8f0; }
+[data-route="point-of-sale"] .border-grey { border: 1px solid #d1d8dd; }
+[data-route="point-of-sale"] .border-white { border: 1px solid #fff; }
+[data-route="point-of-sale"] .border-b-grey { border-bottom: 1px solid #d1d8dd; }
+[data-route="point-of-sale"] .border-t-grey { border-top: 1px solid #d1d8dd; }
+[data-route="point-of-sale"] .border-r-grey { border-right: 1px solid #d1d8dd; }
+[data-route="point-of-sale"] .text-dark-grey { color: #5f5f5f; }
+[data-route="point-of-sale"] .text-grey { color: #8d99a6; }
+[data-route="point-of-sale"] .text-grey-100 { color: #d1d8dd; }
+[data-route="point-of-sale"] .text-grey-200 { color: #a0aec0; }
+[data-route="point-of-sale"] .bg-green-200 { background-color: #c6f6d5; }
+[data-route="point-of-sale"] .text-bold { font-weight: bold; }
+[data-route="point-of-sale"] .italic { font-style: italic; }
+[data-route="point-of-sale"] .font-weight-450 { font-weight: 450; }
+[data-route="point-of-sale"] .justify-around { justify-content: space-around; }
+[data-route="point-of-sale"] .justify-between { justify-content: space-between; }
+[data-route="point-of-sale"] .justify-center { justify-content: center; }
+[data-route="point-of-sale"] .justify-end { justify-content: flex-end; }
+[data-route="point-of-sale"] .bg-white { background-color: white; }
+[data-route="point-of-sale"] .bg-light-grey { background-color: #f0f4f7; }
+[data-route="point-of-sale"] .bg-grey-100 { background-color: #f7fafc; }
+[data-route="point-of-sale"] .bg-grey-200 { background-color: #edf2f7; }
+[data-route="point-of-sale"] .bg-grey { background-color: #f4f5f6; }
+[data-route="point-of-sale"] .text-center { text-align: center; }
+[data-route="point-of-sale"] .text-right { text-align: right; }
+[data-route="point-of-sale"] .text-sm { font-size: 1rem; }
+[data-route="point-of-sale"] .text-md-0 { font-size: 1.25rem; }
+[data-route="point-of-sale"] .text-md { font-size: 1.4rem; }
+[data-route="point-of-sale"] .text-lg { font-size: 1.6rem; }
+[data-route="point-of-sale"] .text-xl { font-size: 2.2rem; }
+[data-route="point-of-sale"] .text-2xl { font-size: 2.8rem; }
+[data-route="point-of-sale"] .text-2-5xl { font-size: 3rem; }
+[data-route="point-of-sale"] .text-3xl { font-size: 3.8rem; }
+[data-route="point-of-sale"] .text-6xl { font-size: 4.8rem; }
+[data-route="point-of-sale"] .line-through { text-decoration: line-through; }
+[data-route="point-of-sale"] .text-primary { color: #5e64ff; }
+[data-route="point-of-sale"] .text-white { color: #fff; }
+[data-route="point-of-sale"] .text-green-500 { color: #48bb78; }
+[data-route="point-of-sale"] .bg-primary { background-color: #5e64ff; }
+[data-route="point-of-sale"] .border-primary { border-color: #5e64ff; }
+[data-route="point-of-sale"] .text-danger { color: #e53e3e; }
+[data-route="point-of-sale"] .scroll-x { overflow-x: scroll;overflow-y: hidden; }
+[data-route="point-of-sale"] .scroll-y { overflow-y: scroll;overflow-x: hidden; }
+[data-route="point-of-sale"] .overflow-hidden { overflow: hidden; }
+[data-route="point-of-sale"] .whitespace-nowrap { white-space: nowrap; }
+[data-route="point-of-sale"] .sticky { position: sticky;  top: -1px; }
+[data-route="point-of-sale"] .bg-white { background-color: #fff; }
+[data-route="point-of-sale"] .bg-selected { background-color: #fffdf4; }
+[data-route="point-of-sale"] .border-dashed { border-width:1px; border-style: dashed; }
+[data-route="point-of-sale"] .z-100 { z-index: 100; }
+
+[data-route="point-of-sale"] .frappe-control { margin: 0 !important;  width: 100%; }
+[data-route="point-of-sale"] .form-control { font-size: 12px; }
+[data-route="point-of-sale"] .form-group { margin: 0 !important; }
+[data-route="point-of-sale"] .pointer { cursor: pointer; }
+[data-route="point-of-sale"] .no-select { user-select: none; }
+[data-route="point-of-sale"] .item-wrapper:hover { transform: scale(1.02, 1.02); }
+[data-route="point-of-sale"] .hover-underline:hover { text-decoration: underline; }
+[data-route="point-of-sale"] .item-wrapper { transition: scale 0.2s ease-in-out; }
+[data-route="point-of-sale"] .cart-items-section .cart-item-wrapper:not(:first-child) { border-top: none; }
+[data-route="point-of-sale"] .customer-transactions .invoice-wrapper:not(:first-child) { border-top: none; }
+
+[data-route="point-of-sale"] .payment-summary-wrapper:last-child { border-bottom: none; }
+[data-route="point-of-sale"] .item-summary-wrapper:last-child { border-bottom: none; }
+[data-route="point-of-sale"] .total-summary-wrapper:last-child { border-bottom: none; }
+[data-route="point-of-sale"] .invoices-container .invoice-wrapper:last-child { border-bottom: none; }
+[data-route="point-of-sale"] .summary-btns:last-child { margin-right: 0px; }
+[data-route="point-of-sale"] ::-webkit-scrollbar { width: 1px }
+
+[data-route="point-of-sale"] .indicator.grey::before { background-color: #8d99a6; }
\ 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 2ce49e7..87b21b7 100644
--- a/erpnext/public/js/controllers/stock_controller.js
+++ b/erpnext/public/js/controllers/stock_controller.js
@@ -55,8 +55,9 @@
 				frappe.route_options = {
 					voucher_no: me.frm.doc.name,
 					from_date: me.frm.doc.posting_date,
-					to_date: me.frm.doc.posting_date,
-					company: me.frm.doc.company
+					to_date: moment(me.frm.doc.modified).format('YYYY-MM-DD'),
+					company: me.frm.doc.company,
+					show_cancelled_entries: me.frm.doc.docstatus === 2
 				};
 				frappe.set_route("query-report", "Stock Ledger");
 			}, __("View"));
@@ -71,9 +72,10 @@
 				frappe.route_options = {
 					voucher_no: me.frm.doc.name,
 					from_date: me.frm.doc.posting_date,
-					to_date: me.frm.doc.posting_date,
+					to_date: moment(me.frm.doc.modified).format('YYYY-MM-DD'),
 					company: me.frm.doc.company,
-					group_by: "Group by Voucher (Consolidated)"
+					group_by: "Group by Voucher (Consolidated)",
+					show_cancelled_entries: me.frm.doc.docstatus === 2
 				};
 				frappe.set_route("query-report", "General Ledger");
 			}, __("View"));
diff --git a/erpnext/public/js/controllers/taxes_and_totals.js b/erpnext/public/js/controllers/taxes_and_totals.js
index b72ceb2..405a33c 100644
--- a/erpnext/public/js/controllers/taxes_and_totals.js
+++ b/erpnext/public/js/controllers/taxes_and_totals.js
@@ -34,12 +34,12 @@
 		this.calculate_discount_amount();
 
 		// Advance calculation applicable to Sales /Purchase Invoice
-		if(in_list(["Sales Invoice", "Purchase Invoice"], this.frm.doc.doctype)
+		if(in_list(["Sales Invoice", "POS Invoice", "Purchase Invoice"], this.frm.doc.doctype)
 			&& this.frm.doc.docstatus < 2 && !this.frm.doc.is_return) {
 			this.calculate_total_advance(update_paid_amount);
 		}
 
-		if (this.frm.doc.doctype == "Sales Invoice" && this.frm.doc.is_pos &&
+		if (in_list(["Sales Invoice", "POS Invoice"], this.frm.doc.doctype) && this.frm.doc.is_pos &&
 			this.frm.doc.is_return) {
 			this.update_paid_amount_for_return();
 		}
@@ -425,7 +425,7 @@
 			? this.frm.doc["taxes"][tax_count - 1].total + flt(this.frm.doc.rounding_adjustment)
 			: this.frm.doc.net_total);
 
-		if(in_list(["Quotation", "Sales Order", "Delivery Note", "Sales Invoice"], this.frm.doc.doctype)) {
+		if(in_list(["Quotation", "Sales Order", "Delivery Note", "Sales Invoice", "POS Invoice"], this.frm.doc.doctype)) {
 			this.frm.doc.base_grand_total = (this.frm.doc.total_taxes_and_charges) ?
 				flt(this.frm.doc.grand_total * this.frm.doc.conversion_rate) : this.frm.doc.base_net_total;
 		} else {
@@ -604,7 +604,7 @@
 		// NOTE:
 		// paid_amount and write_off_amount is only for POS/Loyalty Point Redemption Invoice
 		// total_advance is only for non POS Invoice
-		if(this.frm.doc.doctype == "Sales Invoice" && this.frm.doc.is_return){
+		if(in_list(["Sales Invoice", "POS Invoice"], this.frm.doc.doctype) && this.frm.doc.is_return){
 			this.calculate_paid_amount();
 		}
 
@@ -612,7 +612,7 @@
 
 		frappe.model.round_floats_in(this.frm.doc, ["grand_total", "total_advance", "write_off_amount"]);
 
-		if(in_list(["Sales Invoice", "Purchase Invoice"], this.frm.doc.doctype)) {
+		if(in_list(["Sales Invoice", "POS Invoice", "Purchase Invoice"], this.frm.doc.doctype)) {
 			var grand_total = this.frm.doc.rounded_total || this.frm.doc.grand_total;
 
 			if(this.frm.doc.party_account_currency == this.frm.doc.currency) {
@@ -634,7 +634,7 @@
 				this.frm.refresh_field("base_paid_amount");
 			}
 
-			if(this.frm.doc.doctype == "Sales Invoice") {
+			if(in_list(["Sales Invoice", "POS Invoice"], this.frm.doc.doctype)) {
 				let total_amount_for_payment = (this.frm.doc.redeem_loyalty_points && this.frm.doc.loyalty_amount)
 					? flt(total_amount_to_pay - this.frm.doc.loyalty_amount, precision("base_grand_total"))
 					: total_amount_to_pay;
@@ -691,11 +691,13 @@
 		if(this.frm.doc.is_pos && (update_paid_amount===undefined || update_paid_amount)) {
 			$.each(this.frm.doc['payments'] || [], function(index, data) {
 				if(data.default && payment_status && total_amount_to_pay > 0) {
-					data.base_amount = flt(total_amount_to_pay, precision("base_amount"));
-					data.amount = flt(total_amount_to_pay / me.frm.doc.conversion_rate, precision("amount"));
+					let base_amount = flt(total_amount_to_pay, precision("base_amount", data));
+					frappe.model.set_value(data.doctype, data.name, "base_amount", base_amount);
+					let amount = flt(total_amount_to_pay / me.frm.doc.conversion_rate, precision("amount", data));
+					frappe.model.set_value(data.doctype, data.name, "amount", amount);
 					payment_status = false;
 				} else if(me.frm.doc.paid_amount) {
-					data.amount = 0.0;
+					frappe.model.set_value(data.doctype, data.name, "amount", 0.0);
 				}
 			});
 		}
@@ -707,7 +709,7 @@
 		var base_paid_amount = 0.0;
 		if(this.frm.doc.is_pos) {
 			$.each(this.frm.doc['payments'] || [], function(index, data){
-				data.base_amount = flt(data.amount * me.frm.doc.conversion_rate, precision("base_amount"));
+				data.base_amount = flt(data.amount * me.frm.doc.conversion_rate, precision("base_amount", data));
 				paid_amount += data.amount;
 				base_paid_amount += data.base_amount;
 			});
@@ -719,14 +721,14 @@
 			paid_amount += flt(this.frm.doc.loyalty_amount / me.frm.doc.conversion_rate, precision("paid_amount"));
 		}
 
-		this.frm.doc.paid_amount = flt(paid_amount, precision("paid_amount"));
-		this.frm.doc.base_paid_amount = flt(base_paid_amount, precision("base_paid_amount"));
+		this.frm.set_value('paid_amount', flt(paid_amount, precision("paid_amount")));
+		this.frm.set_value('base_paid_amount', flt(base_paid_amount, precision("base_paid_amount")));
 	},
 
 	calculate_change_amount: function(){
 		this.frm.doc.change_amount = 0.0;
 		this.frm.doc.base_change_amount = 0.0;
-		if(this.frm.doc.doctype == "Sales Invoice"
+		if(in_list(["Sales Invoice", "POS Invoice"], this.frm.doc.doctype)
 			&& this.frm.doc.paid_amount > this.frm.doc.grand_total && !this.frm.doc.is_return) {
 
 			var payment_types = $.map(this.frm.doc.payments, function(d) { return d.type; });
diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js
index ca897dd..4e50f3d 100644
--- a/erpnext/public/js/controllers/transaction.js
+++ b/erpnext/public/js/controllers/transaction.js
@@ -159,6 +159,26 @@
 				};
 			});
 		}
+		if (this.frm.fields_dict["items"].grid.get_field("cost_center")) {
+			this.frm.set_query("cost_center", "items", function(doc) {
+				return {
+					filters: {
+						"company": doc.company,
+						"is_group": 0
+					}
+				};
+			});
+		}
+
+		if (this.frm.fields_dict["items"].grid.get_field("expense_account")) {
+			this.frm.set_query("expense_account", "items", function(doc) {
+				return {
+					filters: {
+						"company": doc.company
+					}
+				};
+			});
+		}
 
 		if(frappe.meta.get_docfield(this.frm.doc.doctype, "pricing_rules")) {
 			this.frm.set_indicator_formatter('pricing_rule', function(doc) {
@@ -631,7 +651,7 @@
 					let child = frappe.model.add_child(me.frm.doc, "taxes");
 					child.charge_type = "On Net Total";
 					child.account_head = tax;
-					child.rate = 0;
+					child.rate = rate;
 				}
 			});
 		}
@@ -1815,7 +1835,8 @@
 
 			if (doc.tax_category)
 				filters['tax_category'] = doc.tax_category;
-
+			if (doc.company)
+				filters['company'] = doc.company;
 			return {
 				query: "erpnext.controllers.queries.get_tax_template",
 				filters: filters
diff --git a/erpnext/public/js/financial_statements.js b/erpnext/public/js/financial_statements.js
index d89d471..459c01b 100644
--- a/erpnext/public/js/financial_statements.js
+++ b/erpnext/public/js/financial_statements.js
@@ -3,7 +3,7 @@
 erpnext.financial_statements = {
 	"filters": get_filters(),
 	"formatter": function(value, row, column, data, default_formatter) {
-		if (column.fieldname=="account") {
+		if (data && column.fieldname=="account") {
 			value = data.account_name || value;
 
 			column.link_onclick =
@@ -13,7 +13,7 @@
 
 		value = default_formatter(value, row, column, data);
 
-		if (!data.parent_account) {
+		if (data && !data.parent_account) {
 			value = $(`<span>${value}</span>`);
 
 			var $value = $(value).css("font-weight", "bold");
diff --git a/erpnext/public/js/help_links.js b/erpnext/public/js/help_links.js
index 17b726e..66ff464 100644
--- a/erpnext/public/js/help_links.js
+++ b/erpnext/public/js/help_links.js
@@ -450,7 +450,7 @@
 ]
 
 frappe.help.help_links['Form/Address'] = [
-	{ label: 'Address', url: docsUrl + 'user/manual/en/CRM/contact' },
+	{ label: 'Address', url: docsUrl + 'user/manual/en/CRM/address' },
 ]
 
 frappe.help.help_links['Form/Contact'] = [
diff --git a/erpnext/public/js/salary_slip_deductions_report_filters.js b/erpnext/public/js/salary_slip_deductions_report_filters.js
index 2420379..2b30e65 100644
--- a/erpnext/public/js/salary_slip_deductions_report_filters.js
+++ b/erpnext/public/js/salary_slip_deductions_report_filters.js
@@ -11,8 +11,8 @@
 			default: frappe.defaults.get_user_default("Company"),
 		},
 		{
-			fieldname: "period",
-			label: __("Period"),
+			fieldname: "month",
+			label: __("Month"),
 			fieldtype: "Select",
 			reqd: 1 ,
 			options: [
@@ -32,6 +32,12 @@
 			default: frappe.datetime.str_to_obj(frappe.datetime.get_today()).getMonth() + 1
 		},
 		{
+			fieldname:"year",
+			label: __("Year"),
+			fieldtype: "Select",
+			reqd: 1
+		},
+		{
 			fieldname: "department",
 			label: __("Department"),
 			fieldtype: "Link",
@@ -43,5 +49,18 @@
 			fieldtype: "Link",
 			options: "Branch",
 		}
-	]
+	],
+
+	"onload": function() {
+		return  frappe.call({
+			method: "erpnext.regional.report.provident_fund_deductions.provident_fund_deductions.get_years",
+			callback: function(r) {
+				var year_filter = frappe.query_report.get_filter('year');
+				year_filter.df.options = r.message;
+				year_filter.df.default = r.message.split("\n")[0];
+				year_filter.refresh();
+				year_filter.set_input(year_filter.df.default);
+			}
+		});
+	}
 }
\ No newline at end of file
diff --git a/erpnext/public/js/shopping_cart.js b/erpnext/public/js/shopping_cart.js
index 44a8cd0..6a923ae 100644
--- a/erpnext/public/js/shopping_cart.js
+++ b/erpnext/public/js/shopping_cart.js
@@ -55,6 +55,7 @@
 	shopping_cart.show_shoppingcart_dropdown();
 	shopping_cart.set_cart_count();
 	shopping_cart.bind_dropdown_cart_buttons();
+	shopping_cart.show_cart_navbar();
 });
 
 $.extend(shopping_cart, {
@@ -177,4 +178,12 @@
 
 	},
 
+	show_cart_navbar: function () {
+		frappe.call({
+			method: "erpnext.shopping_cart.doctype.shopping_cart_settings.shopping_cart_settings.is_cart_enabled",
+			callback: function(r) {
+				$(".shopping-cart").toggleClass('hidden', r.message ? false : true);
+			}
+		});
+	}
 });
diff --git a/erpnext/public/js/utils/party.js b/erpnext/public/js/utils/party.js
index 99c1b8a..0653267 100644
--- a/erpnext/public/js/utils/party.js
+++ b/erpnext/public/js/utils/party.js
@@ -4,7 +4,7 @@
 frappe.provide("erpnext.utils");
 
 erpnext.utils.get_party_details = function(frm, method, args, callback) {
-	if(!method) {
+	if (!method) {
 		method = "erpnext.accounts.party.get_party_details";
 	}
 
@@ -22,12 +22,12 @@
 		}
 	}
 
-	if(!args) {
-		if((frm.doctype != "Purchase Order" && frm.doc.customer)
+	if (!args) {
+		if ((frm.doctype != "Purchase Order" && frm.doc.customer)
 			|| (frm.doc.party_name && in_list(['Quotation', 'Opportunity'], frm.doc.doctype))) {
 
 			let party_type = "Customer";
-			if(frm.doc.quotation_to && frm.doc.quotation_to === "Lead") {
+			if (frm.doc.quotation_to && frm.doc.quotation_to === "Lead") {
 				party_type = "Lead";
 			}
 
@@ -36,7 +36,7 @@
 				party_type: party_type,
 				price_list: frm.doc.selling_price_list
 			};
-		} else if(frm.doc.supplier) {
+		} else if (frm.doc.supplier) {
 			args = {
 				party: frm.doc.supplier,
 				party_type: "Supplier",
@@ -78,13 +78,17 @@
 			args.posting_date = frm.doc.posting_date || frm.doc.transaction_date;
 		}
 	}
-	if(!args || !args.party) return;
+	if (!args || !args.party) return;
 
-	if(frappe.meta.get_docfield(frm.doc.doctype, "taxes")) {
-		if(!erpnext.utils.validate_mandatory(frm, "Posting/Transaction Date",
+	if (frappe.meta.get_docfield(frm.doc.doctype, "taxes")) {
+		if (!erpnext.utils.validate_mandatory(frm, "Posting / Transaction Date",
 			args.posting_date, args.party_type=="Customer" ? "customer": "supplier")) return;
 	}
 
+	if (!erpnext.utils.validate_mandatory(frm, "Company", frm.doc.company, args.party_type=="Customer" ? "customer": "supplier")) {
+		return;
+	}
+
 	args.currency = frm.doc.currency;
 	args.company = frm.doc.company;
 	args.doctype = frm.doc.doctype;
@@ -92,14 +96,14 @@
 		method: method,
 		args: args,
 		callback: function(r) {
-			if(r.message) {
+			if (r.message) {
 				frm.supplier_tds = r.message.supplier_tds;
 				frm.updating_party_details = true;
 				frappe.run_serially([
 					() => frm.set_value(r.message),
 					() => {
 						frm.updating_party_details = false;
-						if(callback) callback();
+						if (callback) callback();
 						frm.refresh();
 						erpnext.utils.add_item(frm);
 					}
@@ -110,9 +114,9 @@
 }
 
 erpnext.utils.add_item = function(frm) {
-	if(frm.is_new()) {
+	if (frm.is_new()) {
 		var prev_route = frappe.get_prev_route();
-		if(prev_route[1]==='Item' && !(frm.doc.items && frm.doc.items.length)) {
+		if (prev_route[1]==='Item' && !(frm.doc.items && frm.doc.items.length)) {
 			// add row
 			var item = frm.add_child('items');
 			frm.refresh_field('items');
@@ -124,23 +128,23 @@
 }
 
 erpnext.utils.get_address_display = function(frm, address_field, display_field, is_your_company_address) {
-	if(frm.updating_party_details) return;
+	if (frm.updating_party_details) return;
 
-	if(!address_field) {
-		if(frm.doctype != "Purchase Order" && frm.doc.customer) {
+	if (!address_field) {
+		if (frm.doctype != "Purchase Order" && frm.doc.customer) {
 			address_field = "customer_address";
-		} else if(frm.doc.supplier) {
+		} else if (frm.doc.supplier) {
 			address_field = "supplier_address";
 		} else return;
 	}
 
-	if(!display_field) display_field = "address_display";
-	if(frm.doc[address_field]) {
+	if (!display_field) display_field = "address_display";
+	if (frm.doc[address_field]) {
 		frappe.call({
 			method: "frappe.contacts.doctype.address.address.get_address_display",
 			args: {"address_dict": frm.doc[address_field] },
 			callback: function(r) {
-				if(r.message) {
+				if (r.message) {
 					frm.set_value(display_field, r.message)
 				}
 			}
@@ -151,15 +155,15 @@
 };
 
 erpnext.utils.set_taxes_from_address = function(frm, triggered_from_field, billing_address_field, shipping_address_field) {
-	if(frm.updating_party_details) return;
+	if (frm.updating_party_details) return;
 
-	if(frappe.meta.get_docfield(frm.doc.doctype, "taxes")) {
-		if(!erpnext.utils.validate_mandatory(frm, "Lead/Customer/Supplier",
+	if (frappe.meta.get_docfield(frm.doc.doctype, "taxes")) {
+		if (!erpnext.utils.validate_mandatory(frm, "Lead / Customer / Supplier",
 			frm.doc.customer || frm.doc.supplier || frm.doc.lead || frm.doc.party_name, triggered_from_field)) {
 			return;
 		}
 
-		if(!erpnext.utils.validate_mandatory(frm, "Posting/Transaction Date",
+		if (!erpnext.utils.validate_mandatory(frm, "Posting / Transaction Date",
 			frm.doc.posting_date || frm.doc.transaction_date, triggered_from_field)) {
 			return;
 		}
@@ -175,8 +179,8 @@
 			"shipping_address": frm.doc[shipping_address_field]
 		},
 		callback: function(r) {
-			if(!r.exc){
-				if(frm.doc.tax_category != r.message) {
+			if (!r.exc){
+				if (frm.doc.tax_category != r.message) {
 					frm.set_value("tax_category", r.message);
 				} else {
 					erpnext.utils.set_taxes(frm, triggered_from_field);
@@ -187,13 +191,17 @@
 };
 
 erpnext.utils.set_taxes = function(frm, triggered_from_field) {
-	if(frappe.meta.get_docfield(frm.doc.doctype, "taxes")) {
-		if(!erpnext.utils.validate_mandatory(frm, "Lead/Customer/Supplier",
+	if (frappe.meta.get_docfield(frm.doc.doctype, "taxes")) {
+		if (!erpnext.utils.validate_mandatory(frm, "Company", frm.doc.company, triggered_from_field)) {
+			return;
+		}
+
+		if (!erpnext.utils.validate_mandatory(frm, "Lead / Customer / Supplier",
 			frm.doc.customer || frm.doc.supplier || frm.doc.lead || frm.doc.party_name, triggered_from_field)) {
 			return;
 		}
 
-		if(!erpnext.utils.validate_mandatory(frm, "Posting/Transaction Date",
+		if (!erpnext.utils.validate_mandatory(frm, "Posting / Transaction Date",
 			frm.doc.posting_date || frm.doc.transaction_date, triggered_from_field)) {
 			return;
 		}
@@ -230,7 +238,7 @@
 			"shipping_address": frm.doc.shipping_address_name
 		},
 		callback: function(r) {
-			if(r.message){
+			if (r.message){
 				frm.set_value("taxes_and_charges", r.message)
 			}
 		}
@@ -238,14 +246,14 @@
 };
 
 erpnext.utils.get_contact_details = function(frm) {
-	if(frm.updating_party_details) return;
+	if (frm.updating_party_details) return;
 
-	if(frm.doc["contact_person"]) {
+	if (frm.doc["contact_person"]) {
 		frappe.call({
 			method: "frappe.contacts.doctype.contact.contact.get_contact_details",
 			args: {contact: frm.doc.contact_person },
 			callback: function(r) {
-				if(r.message)
+				if (r.message)
 					frm.set_value(r.message);
 			}
 		})
@@ -253,10 +261,10 @@
 }
 
 erpnext.utils.validate_mandatory = function(frm, label, value, trigger_on) {
-	if(!value) {
+	if (!value) {
 		frm.doc[trigger_on] = "";
 		refresh_field(trigger_on);
-		frappe.msgprint(__("Please enter {0} first", [label]));
+		frappe.throw({message:__("Please enter {0} first", [label]), title:__("Mandatory")});
 		return false;
 	}
 	return true;
@@ -271,12 +279,12 @@
 				address: frm.doc.shipping_address
 			},
 			callback: function(r){
-				if(r.message){
+				if (r.message){
 					frm.set_value("shipping_address", r.message[0]) //Address title or name
 					frm.set_value("shipping_address_display", r.message[1]) //Address to be displayed on the page
 				}
 
-				if(callback){
+				if (callback){
 					return callback();
 				}
 			}
diff --git a/erpnext/public/js/utils/serial_no_batch_selector.js b/erpnext/public/js/utils/serial_no_batch_selector.js
index d75633e..42f9cabc 100644
--- a/erpnext/public/js/utils/serial_no_batch_selector.js
+++ b/erpnext/public/js/utils/serial_no_batch_selector.js
@@ -43,6 +43,7 @@
 				label: __(me.warehouse_details.type),
 				default: typeof me.warehouse_details.name == "string" ? me.warehouse_details.name : '',
 				onchange: function(e) {
+					me.warehouse_details.name = this.get_value();
 
 					if(me.has_batch && !me.has_serial_no) {
 						fields = fields.concat(me.get_batch_fields());
@@ -50,7 +51,6 @@
 						fields = fields.concat(me.get_serial_no_fields());
 					}
 
-					me.warehouse_details.name = this.get_value();
 					var batches = this.layout.fields_dict.batches;
 					if(batches) {
 						batches.grid.df.data = [];
@@ -98,8 +98,13 @@
 					numbers.then((data) => {
 						let auto_fetched_serial_numbers = data.message;
 						let records_length = auto_fetched_serial_numbers.length;
+						if (!records_length) {
+							const warehouse = me.dialog.fields_dict.warehouse.get_value().bold();
+							frappe.msgprint(__(`Serial numbers unavailable for Item ${me.item.item_code.bold()} 
+								under warehouse ${warehouse}. Please try changing warehouse.`));
+						}
 						if (records_length < qty) {
-							frappe.msgprint(`Fetched only ${records_length} serial numbers.`);
+							frappe.msgprint(__(`Fetched only ${records_length} available serial numbers.`));
 						}
 						let serial_no_list_field = this.dialog.fields_dict.serial_no;
 						numbers = auto_fetched_serial_numbers.join('\n');
@@ -445,6 +450,28 @@
 			serial_no_filters['warehouse'] = me.warehouse_details.name;
 		}
 
+		if (me.frm.doc.doctype === 'POS Invoice' && !this.showing_reserved_serial_nos_error) {
+			frappe.call({
+				method: "erpnext.stock.doctype.serial_no.serial_no.get_pos_reserved_serial_nos",
+				args: {
+					item_code: me.item_code,
+					warehouse: typeof me.warehouse_details.name == "string" ? me.warehouse_details.name : ''
+				}
+			}).then((data) => {
+				if (!data.message[1].length) {
+					this.showing_reserved_serial_nos_error = true;
+					const warehouse = me.dialog.fields_dict.warehouse.get_value().bold();
+					const d = frappe.msgprint(__(`Serial numbers unavailable for Item ${me.item.item_code.bold()} 
+						under warehouse ${warehouse}. Please try changing warehouse.`));
+					d.get_close_btn().on('click', () => {
+						this.showing_reserved_serial_nos_error = false;
+						d.hide();
+					});
+				}
+				serial_no_filters['name'] = ["not in", data.message[0]]
+			})
+		}
+
 		return [
 			{fieldtype: 'Section Break', label: __('Serial Numbers')},
 			{
diff --git a/erpnext/quality_management/doctype/quality_feedback/quality_feedback.js b/erpnext/quality_management/doctype/quality_feedback/quality_feedback.js
index 63747af..dac6ac4 100644
--- a/erpnext/quality_management/doctype/quality_feedback/quality_feedback.js
+++ b/erpnext/quality_management/doctype/quality_feedback/quality_feedback.js
@@ -5,21 +5,28 @@
 	refresh: function(frm) {
 		frm.set_value("date", frappe.datetime.get_today());
 	},
-	template: function(frm){
-		frappe.call({
-			"method": "frappe.client.get",
-			args: {
-				doctype: "Quality Feedback Template",
-				name: frm.doc.template
-			},
-			callback: function(data){
-				frm.fields_dict.parameters.grid.remove_all();
-				for (var i in data.message.parameters){
-					frm.add_child("parameters");
-					frm.fields_dict.parameters.get_value()[i].parameter = data.message.parameters[i].parameter;
+
+	template: function(frm) {
+		if (frm.doc.template) {
+			frappe.call({
+				"method": "frappe.client.get",
+				args: {
+					doctype: "Quality Feedback Template",
+					name: frm.doc.template
+				},
+				callback: function(data) {
+					if (data && data.message) {
+						frm.fields_dict.parameters.grid.remove_all();
+
+						// fetch parameters from template and autofill
+						for (let template_parameter of data.message.parameters) {
+							let row = frm.add_child("parameters");
+							row.parameter = template_parameter.parameter;
+						}
+						frm.refresh();
+					}
 				}
-				frm.refresh();
-			}
-		});
+			});
+		}
 	}
 });
diff --git a/erpnext/quality_management/doctype/quality_feedback/quality_feedback.json b/erpnext/quality_management/doctype/quality_feedback/quality_feedback.json
index 460438a..ab9084f 100644
--- a/erpnext/quality_management/doctype/quality_feedback/quality_feedback.json
+++ b/erpnext/quality_management/doctype/quality_feedback/quality_feedback.json
@@ -1,4 +1,5 @@
 {
+ "actions": [],
  "autoname": "format:FDBK-{#####}",
  "creation": "2019-05-26 21:23:05.308379",
  "doctype": "DocType",
@@ -53,12 +54,13 @@
   {
    "fieldname": "document_name",
    "fieldtype": "Dynamic Link",
-   "label": "Name",
+   "label": "Feedback By",
    "options": "document_type",
    "reqd": 1
   }
  ],
- "modified": "2019-05-28 15:16:01.161662",
+ "links": [],
+ "modified": "2020-07-03 15:50:58.589302",
  "modified_by": "Administrator",
  "module": "Quality Management",
  "name": "Quality Feedback",
diff --git a/erpnext/quality_management/doctype/quality_feedback_template/quality_feedback_template.json b/erpnext/quality_management/doctype/quality_feedback_template/quality_feedback_template.json
index 31efd04..bdc9dba 100644
--- a/erpnext/quality_management/doctype/quality_feedback_template/quality_feedback_template.json
+++ b/erpnext/quality_management/doctype/quality_feedback_template/quality_feedback_template.json
@@ -1,4 +1,5 @@
 {
+ "actions": [],
  "autoname": "format:TMPL-{template}",
  "creation": "2019-05-26 21:17:24.283061",
  "doctype": "DocType",
@@ -30,10 +31,12 @@
    "fieldname": "parameters",
    "fieldtype": "Table",
    "label": "Parameters",
-   "options": "Quality Feedback Template Parameter"
+   "options": "Quality Feedback Template Parameter",
+   "reqd": 1
   }
  ],
- "modified": "2019-05-26 21:48:47.770610",
+ "links": [],
+ "modified": "2020-07-03 16:06:03.749415",
  "modified_by": "Administrator",
  "module": "Quality Management",
  "name": "Quality Feedback Template",
diff --git a/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.js b/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.js
index a1cea8f..c744266 100644
--- a/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.js
+++ b/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.js
@@ -3,6 +3,7 @@
 
 frappe.ui.form.on('GSTR 3B Report', {
 	refresh : function(frm) {
+		frm.doc.__unsaved = 1;
 		if(!frm.is_new()) {
 			frm.set_intro(__("Please save the report again to rebuild or update"));
 			frm.add_custom_button(__('Download JSON'), function() {
diff --git a/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.py b/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.py
index 619734f..2d306ba 100644
--- a/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.py
+++ b/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.py
@@ -243,20 +243,15 @@
 
 		osup_det = self.report_dict["sup_details"]["osup_det"]
 
-		for d in inter_state_supply.get("Unregistered", []):
-			self.report_dict["inter_sup"]["unreg_details"].append(d)
-			osup_det["txval"] = flt(osup_det["txval"] + d["txval"], 2)
-			osup_det["iamt"] = flt(osup_det["iamt"] + d["iamt"], 2)
+		for key, value in iteritems(inter_state_supply):
+			if key[0] == "Unregistered":
+				self.report_dict["inter_sup"]["unreg_details"].append(value)
 
-		for d in inter_state_supply.get("Registered Composition", []):
-			self.report_dict["inter_sup"]["comp_details"].append(d)
-			osup_det["txval"] = flt(osup_det["txval"] + d["txval"], 2)
-			osup_det["iamt"] = flt(osup_det["iamt"] + d["iamt"], 2)
+			if key[0] == "Registered Composition":
+				self.report_dict["inter_sup"]["comp_details"].append(value)
 
-		for d in inter_state_supply.get("UIN Holders", []):
-			self.report_dict["inter_sup"]["uin_details"].append(d)
-			osup_det["txval"] = flt(osup_det["txval"] + d["txval"], 2)
-			osup_det["iamt"] = flt(osup_det["iamt"] + d["iamt"], 2)
+			if key[0] == "UIN Holders":
+				self.report_dict["inter_sup"]["uin_details"].append(value)
 
 	def get_total_taxable_value(self, doctype, reverse_charge):
 
@@ -301,41 +296,55 @@
 			(self.month_no, self.year, self.company, self.gst_details.get("gstin")), as_dict=1)[0].total
 
 	def get_inter_state_supplies(self, state_number):
-
-		inter_state_supply_taxable_value = frappe.db.sql(""" select sum(s.net_total) as total, s.place_of_supply, s.gst_category
-			from `tabSales Invoice` s where s.docstatus = 1 and month(s.posting_date) = %s and year(s.posting_date) = %s
-			and s.company = %s and s.company_gstin = %s and s.gst_category in ('Unregistered', 'Registered Composition', 'UIN Holders')
-			group by s.gst_category, s.place_of_supply""", (self.month_no, self.year, self.company, self.gst_details.get("gstin")), as_dict=1)
-
-		inter_state_supply_tax = frappe.db.sql(""" select sum(t.tax_amount_after_discount_amount) as tax_amount, s.place_of_supply, s.gst_category
-			from `tabSales Invoice` s, `tabSales Taxes and Charges` t
+		inter_state_supply_tax = frappe.db.sql(""" select t.account_head, t.tax_amount_after_discount_amount as tax_amount,
+			s.name, s.net_total, s.place_of_supply, s.gst_category from `tabSales Invoice` s, `tabSales Taxes and Charges` t
 			where t.parent = s.name and s.docstatus = 1 and month(s.posting_date) = %s and year(s.posting_date) = %s
 			and s.company = %s and s.company_gstin = %s and s.gst_category in ('Unregistered', 'Registered Composition', 'UIN Holders')
-			group by s.gst_category, s.place_of_supply""", (self.month_no, self.year, self.company, self.gst_details.get("gstin")), as_dict=1)
+		""", (self.month_no, self.year, self.company, self.gst_details.get("gstin")), as_dict=1)
 
-		inter_state_supply_tax_mapping={}
+		inter_state_supply_tax_mapping = {}
 		inter_state_supply_details = {}
 
 		for d in inter_state_supply_tax:
-			inter_state_supply_tax_mapping.setdefault(d.place_of_supply, d.tax_amount)
+			inter_state_supply_tax_mapping.setdefault(d.name, {
+				'place_of_supply': d.place_of_supply,
+				'taxable_value': d.net_total,
+				'camt': 0.0,
+				'samt': 0.0,
+				'iamt': 0.0,
+				'csamt': 0.0
+			})
 
-		for d in inter_state_supply_taxable_value:
-			inter_state_supply_details.setdefault(
-				d.gst_category, []
-			)
+			if d.account_head in [d.cgst_account for d in self.account_heads]:
+				inter_state_supply_tax_mapping[d.name]['camt'] += d.tax_amount
 
+			if d.account_head in [d.sgst_account for d in self.account_heads]:
+				inter_state_supply_tax_mapping[d.name]['samt'] += d.tax_amount
+
+			if d.account_head in [d.igst_account for d in self.account_heads]:
+				inter_state_supply_tax_mapping[d.name]['iamt'] += d.tax_amount
+
+			if d.account_head in [d.cess_account for d in self.account_heads]:
+				inter_state_supply_tax_mapping[d.name]['csamt'] += d.tax_amount
+
+		for key, value in iteritems(inter_state_supply_tax_mapping):
 			if d.place_of_supply:
+				osup_det = self.report_dict["sup_details"]["osup_det"]
+				osup_det["txval"] = flt(osup_det["txval"] + value['taxable_value'], 2)
+				osup_det["iamt"] = flt(osup_det["iamt"] + value['iamt'], 2)
+				osup_det["camt"] = flt(osup_det["camt"] + value['camt'], 2)
+				osup_det["samt"] = flt(osup_det["samt"] + value['samt'], 2)
+				osup_det["csamt"] = flt(osup_det["csamt"] + value['csamt'], 2)
+
 				if state_number != d.place_of_supply.split("-")[0]:
-					inter_state_supply_details[d.gst_category].append({
+					inter_state_supply_details.setdefault((d.gst_category, d.place_of_supply), {
+						"txval": 0.0,
 						"pos": d.place_of_supply.split("-")[0],
-						"txval": flt(d.total, 2),
-						"iamt": flt(inter_state_supply_tax_mapping.get(d.place_of_supply), 2)
+						"iamt": 0.0
 					})
-				else:
-					osup_det = self.report_dict["sup_details"]["osup_det"]
-					osup_det["txval"] = flt(osup_det["txval"] + d.total, 2)
-					osup_det["camt"] = flt(osup_det["camt"] + inter_state_supply_tax_mapping.get(d.place_of_supply)/2, 2)
-					osup_det["samt"] = flt(osup_det["samt"] + inter_state_supply_tax_mapping.get(d.place_of_supply)/2, 2)
+
+					inter_state_supply_details[(d.gst_category, d.place_of_supply)]['txval'] += value['taxable_value']
+					inter_state_supply_details[(d.gst_category, d.place_of_supply)]['iamt'] += value['iamt']
 
 		return inter_state_supply_details
 
diff --git a/erpnext/regional/india/utils.py b/erpnext/regional/india/utils.py
index 05ffa87..fe7e0c8 100644
--- a/erpnext/regional/india/utils.py
+++ b/erpnext/regional/india/utils.py
@@ -1,7 +1,7 @@
 from __future__ import unicode_literals
 import frappe, re, json
 from frappe import _
-from frappe.utils import cstr, flt, date_diff, nowdate
+from frappe.utils import cstr, flt, date_diff, nowdate, round_based_on_smallest_currency_fraction, money_in_words
 from erpnext.regional.india import states, state_numbers
 from erpnext.controllers.taxes_and_totals import get_itemised_tax, get_itemised_taxable_amount
 from erpnext.controllers.accounts_controller import get_taxes_and_charges
@@ -458,19 +458,23 @@
 
 @frappe.whitelist()
 def download_ewb_json():
-	data = frappe._dict(frappe.local.form_dict)
-
-	frappe.local.response.filecontent = json.dumps(data['data'], indent=4, sort_keys=True)
+	data = json.loads(frappe.local.form_dict.data)
+	frappe.local.response.filecontent = json.dumps(data, indent=4, sort_keys=True)
 	frappe.local.response.type = 'download'
 
-	billList = json.loads(data['data'])['billLists']
+	filename_prefix = 'Bulk'
+	docname = frappe.local.form_dict.docname
+	if docname:
+		if docname.startswith('['):
+			docname = json.loads(docname)
+			if len(docname) == 1:
+				docname = docname[0]
 
-	if len(billList) > 1:
-		doc_name = 'Bulk'
-	else:
-		doc_name = data['docname']
+		if not isinstance(docname, list):
+			# removes characters not allowed in a filename (https://stackoverflow.com/a/38766141/4767738)
+			filename_prefix = re.sub('[^\w_.)( -]', '', docname)
 
-	frappe.local.response.filename = '{0}_e-WayBill_Data_{1}.json'.format(doc_name, frappe.utils.random_string(5))
+	frappe.local.response.filename = '{0}_e-WayBill_Data_{1}.json'.format(filename_prefix, frappe.utils.random_string(5))
 
 @frappe.whitelist()
 def get_gstins_for_company(company):
@@ -644,6 +648,7 @@
 	else:
 		return int(state_code)
 
+@frappe.whitelist()
 def get_gst_accounts(company, account_wise=False):
 	gst_accounts = frappe._dict()
 	gst_settings_accounts = frappe.get_all("GST Account",
@@ -662,14 +667,55 @@
 
 	return gst_accounts
 
-def make_reverse_charge_entries(doc, method):
+def update_grand_total_for_rcm(doc, method):
 	country = frappe.get_cached_value('Company', doc.company, 'country')
 
 	if country != 'India':
 		return
 
 	if doc.reverse_charge == 'Y':
-		gl_entries = []
+		gst_accounts = get_gst_accounts(doc.company)
+		gst_account_list = gst_accounts.get('cgst_account') + gst_accounts.get('sgst_account') \
+			+ gst_accounts.get('igst_account')
+
+		gst_tax = 0
+		for tax in doc.get('taxes'):
+			if tax.category not in ("Total", "Valuation and Total"):
+				continue
+
+			if flt(tax.base_tax_amount_after_discount_amount) and tax.account_head in gst_account_list:
+				gst_tax += tax.base_tax_amount_after_discount_amount
+
+		doc.taxes_and_charges_added -= gst_tax
+		doc.total_taxes_and_charges -= gst_tax
+
+		update_totals(gst_tax, doc)
+
+def update_totals(gst_tax, doc):
+	doc.grand_total -= gst_tax
+
+	if doc.meta.get_field("rounded_total"):
+		if doc.is_rounded_total_disabled():
+			doc.outstanding_amount = doc.grand_total
+		else:
+			doc.rounded_total = round_based_on_smallest_currency_fraction(doc.grand_total,
+				doc.currency, doc.precision("rounded_total"))
+
+			doc.rounding_adjustment += flt(doc.rounded_total - doc.grand_total,
+				doc.precision("rounding_adjustment"))
+
+			doc.outstanding_amount = doc.rounded_total or doc.grand_total
+
+	doc.in_words = money_in_words(doc.grand_total, doc.currency)
+	doc.set_payment_schedule()
+
+def make_regional_gl_entries(gl_entries, doc):
+	country = frappe.get_cached_value('Company', doc.company, 'country')
+
+	if country != 'India':
+		return
+
+	if doc.reverse_charge == 'Y':
 		gst_accounts = get_gst_accounts(doc.company)
 		gst_account_list = gst_accounts.get('cgst_account') + gst_accounts.get('sgst_account') \
 			+ gst_accounts.get('igst_account')
@@ -694,19 +740,4 @@
 					}, account_currency, item=tax)
 				)
 
-				gl_entries.append(doc.get_gl_dict(
-					{
-						"account": doc.credit_to if doc.doctype == 'Purchase Invoice' else doc.debit_to,
-						"cost_center": doc.cost_center,
-						"posting_date": doc.posting_date,
-						"party_type": 'Supplier',
-						"party": doc.supplier,
-						"against": tax.account_head,
-						"debit": tax.base_tax_amount_after_discount_amount,
-						"debit_in_account_currency": tax.base_tax_amount_after_discount_amount \
-							if account_currency==doc.company_currency \
-							else tax.tax_amount_after_discount_amount
-					}, account_currency, item=doc)
-				)
-
-		make_gl_entries(gl_entries)
\ No newline at end of file
+	return gl_entries
\ No newline at end of file
diff --git a/erpnext/regional/report/datev/datev.js b/erpnext/regional/report/datev/datev.js
index d8638ab..55f12cf 100644
--- a/erpnext/regional/report/datev/datev.js
+++ b/erpnext/regional/report/datev/datev.js
@@ -30,7 +30,7 @@
 		}
 	],
 	onload: function(query_report) {
-		query_report.page.add_inner_button("Download DATEV Export", () => {
+		query_report.page.add_menu_item(__("Download DATEV File"), () => {
 			const filters = JSON.stringify(query_report.get_values());
 			window.open(`/api/method/erpnext.regional.report.datev.datev.download_datev_csv?filters=${filters}`);
 		});
diff --git a/erpnext/regional/report/datev/datev.py b/erpnext/regional/report/datev/datev.py
index a8e40cc..7fec94e 100644
--- a/erpnext/regional/report/datev/datev.py
+++ b/erpnext/regional/report/datev/datev.py
@@ -8,17 +8,18 @@
   all required columns. Used to import the data into the DATEV Software.
 """
 from __future__ import unicode_literals
+
 import datetime
 import json
-import zlib
 import zipfile
 import six
+import frappe
+import pandas as pd
+
+from frappe import _
 from csv import QUOTE_NONNUMERIC
 from six import BytesIO
 from six import string_types
-import frappe
-from frappe import _
-import pandas as pd
 from .datev_constants import DataCategory
 from .datev_constants import Transactions
 from .datev_constants import DebtorsCreditors
@@ -130,8 +131,10 @@
 		SELECT
 
 			acc.account_number as 'Konto',
-			cus.customer_name as 'Name (Adressatentyp Unternehmen)',
-			case cus.customer_type when 'Individual' then 1 when 'Company' then 2 else 0 end as 'Adressatentyp',
+			CASE cus.customer_type WHEN 'Company' THEN cus.customer_name ELSE null END as 'Name (Adressatentyp Unternehmen)',
+			CASE cus.customer_type WHEN 'Individual' THEN con.last_name ELSE null END as 'Name (Adressatentyp natürl. Person)',
+			CASE cus.customer_type WHEN 'Individual' THEN con.first_name ELSE null END as 'Vorname (Adressatentyp natürl. Person)',
+			CASE cus.customer_type WHEN 'Individual' THEN '1' WHEN 'Company' THEN '2' ELSE '0' end as 'Adressatentyp',
 			adr.address_line1 as 'Straße',
 			adr.pincode as 'Postleitzahl',
 			adr.city as 'Ort',
@@ -140,8 +143,7 @@
 			con.email_id as 'E-Mail',
 			coalesce(con.mobile_no, con.phone) as 'Telefon',
 			cus.website as 'Internet',
-			cus.tax_id as 'Steuernummer',
-			ccl.credit_limit as 'Kreditlimit (Debitor)'
+			cus.tax_id as 'Steuernummer'
 
 		FROM `tabParty Account` par
 
@@ -160,10 +162,6 @@
 			left join `tabContact` con
 			on con.name = cus.customer_primary_contact
 
-			left join `tabCustomer Credit Limit` ccl
-			on ccl.parent = cus.name
-			and ccl.company = par.company
-
 		WHERE par.company = %(company)s
 		AND par.parenttype = 'Customer'""", filters, as_dict=1)
 
@@ -179,8 +177,10 @@
 		SELECT
 
 			acc.account_number as 'Konto',
-			sup.supplier_name as 'Name (Adressatentyp Unternehmen)',
-			case sup.supplier_type when 'Individual' then '1' when 'Company' then '2' else '0' end as 'Adressatentyp',
+			CASE sup.supplier_type WHEN 'Company' THEN sup.supplier_name ELSE null END as 'Name (Adressatentyp Unternehmen)',
+			CASE sup.supplier_type WHEN 'Individual' THEN con.last_name ELSE null END as 'Name (Adressatentyp natürl. Person)',
+			CASE sup.supplier_type WHEN 'Individual' THEN con.first_name ELSE null END as 'Vorname (Adressatentyp natürl. Person)',
+			CASE sup.supplier_type WHEN 'Individual' THEN '1' WHEN 'Company' THEN '2' ELSE '0' end as 'Adressatentyp',
 			adr.address_line1 as 'Straße',
 			adr.pincode as 'Postleitzahl',
 			adr.city as 'Ort',
@@ -226,9 +226,18 @@
 
 
 def get_account_names(filters):
-	return frappe.get_list("Account", 
-		fields=["account_number as Konto", "name as Kontenbeschriftung"], 
-		filters={"company": filters.get("company"), "is_group": "0"})
+	return frappe.db.sql("""
+		SELECT
+
+			account_number as 'Konto',
+			LEFT(account_name, 40) as 'Kontenbeschriftung',
+			'de-DE' as 'Sprach-ID'
+
+		FROM `tabAccount`
+		WHERE company = %(company)s
+		AND is_group = 0
+		AND account_number != ''
+	""", filters, as_dict=1)
 
 
 def get_datev_csv(data, filters, csv_class):
@@ -287,9 +296,7 @@
 
 
 def get_header(filters, csv_class):
-	coa = frappe.get_value("Company", filters.get("company"), "chart_of_accounts")
-	description = filters.get("voucher_type", csv_class.FORMAT_NAME)
-	coa_used = "04" if "SKR04" in coa else ("03" if "SKR03" in coa else "")
+	description = filters.get('voucher_type', csv_class.FORMAT_NAME)
 
 	header = [
 		# DATEV format
@@ -316,19 +323,19 @@
 		# J = Imported by -- stays empty
 		'',
 		# K = Tax consultant number (Beraternummer)
-		frappe.get_value("DATEV Settings", filters.get("company"), "consultant_number"),
+		filters.get('consultant_number', '0000000'),
 		# L = Tax client number (Mandantennummer)
-		frappe.get_value("DATEV Settings", filters.get("company"), "client_number"),
+		filters.get('client_number', '00000'),
 		# M = Start of the fiscal year (Wirtschaftsjahresbeginn)
 		frappe.utils.formatdate(frappe.defaults.get_user_default("year_start_date"), "yyyyMMdd"),
 		# N = Length of account numbers (Sachkontenlänge)
-		'4',
+		'%d' % filters.get('acc_len', 4),
 		# O = Transaction batch start date (YYYYMMDD)
-		frappe.utils.formatdate(filters.get('from_date'), "yyyyMMdd"),
+		frappe.utils.formatdate(filters.get('from_date'), "yyyyMMdd") if csv_class.DATA_CATEGORY == DataCategory.TRANSACTIONS else '',
 		# P = Transaction batch end date (YYYYMMDD)
-		frappe.utils.formatdate(filters.get('to_date'), "yyyyMMdd"),
+		frappe.utils.formatdate(filters.get('to_date'), "yyyyMMdd") if csv_class.DATA_CATEGORY == DataCategory.TRANSACTIONS else '',
 		# Q = Description (for example, "Sales Invoice") Max. 30 chars
-		'"{}"'.format(_(description)),
+		'"{}"'.format(_(description)) if csv_class.DATA_CATEGORY == DataCategory.TRANSACTIONS else '',
 		# R = Diktatkürzel
 		'',
 		# S = Buchungstyp
@@ -343,12 +350,12 @@
 		#	40 = Kalkulatorik
 		#	11 = Reserviert
 		#	12 = Reserviert
-		'0',
+		'0' if csv_class.DATA_CATEGORY == DataCategory.TRANSACTIONS else '',
 		# U = Festschreibung
 		# TODO: Filter by Accounting Period. In export for closed Accounting Period, this will be "1"
 		'0',
 		# V = Default currency, for example, "EUR"
-		'"%s"' % frappe.get_value("Company", filters.get("company"), "default_currency"),
+		'"%s"' % filters.get('default_currency', 'EUR') if csv_class.DATA_CATEGORY == DataCategory.TRANSACTIONS else '',
 		# reserviert
 		'',
 		# Derivatskennzeichen
@@ -358,7 +365,7 @@
 		# reserviert
 		'',
 		# SKR
-		'"%s"' % coa_used,
+		'"%s"' % filters.get('skr', '04'),
 		# Branchen-Lösungs-ID
 		'',
 		# reserviert
@@ -389,6 +396,18 @@
 
 	validate(filters)
 
+	# set chart of accounts used
+	coa = frappe.get_value('Company', filters.get('company'), 'chart_of_accounts')
+	filters['skr'] = '04' if 'SKR04' in coa else ('03' if 'SKR03' in coa else '')
+
+	# set account number length
+	account_numbers = frappe.get_list('Account', fields=['account_number'], filters={'is_group': 0, 'account_number': ('!=', '')})
+	filters['acc_len'] = max([len(a.account_number) for a in account_numbers])
+
+	filters['consultant_number'] = frappe.get_value('DATEV Settings', filters.get('company'), 'consultant_number')
+	filters['client_number'] = frappe.get_value('DATEV Settings', filters.get('company'), 'client_number')
+	filters['default_currency'] = frappe.get_value('Company', filters.get('company'), 'default_currency')
+
 	# This is where my zip will be written
 	zip_buffer = BytesIO()
 	# This is my zip file
diff --git a/erpnext/regional/report/datev/datev_constants.py b/erpnext/regional/report/datev/datev_constants.py
index a059ed3..e063703 100644
--- a/erpnext/regional/report/datev/datev_constants.py
+++ b/erpnext/regional/report/datev/datev_constants.py
@@ -465,60 +465,71 @@
 		"label": "Umsatz (ohne Soll/Haben-Kz)",
 		"fieldname": "Umsatz (ohne Soll/Haben-Kz)",
 		"fieldtype": "Currency",
+		"width": 100
 	},
 	{
 		"label": "Soll/Haben-Kennzeichen",
 		"fieldname": "Soll/Haben-Kennzeichen",
 		"fieldtype": "Data",
+		"width": 100
 	},
 	{
 		"label": "Konto",
 		"fieldname": "Konto",
 		"fieldtype": "Data",
+		"width": 100
 	},
 	{
 		"label": "Gegenkonto (ohne BU-Schlüssel)",
 		"fieldname": "Gegenkonto (ohne BU-Schlüssel)",
 		"fieldtype": "Data",
+		"width": 100
 	},
 	{
 		"label": "Belegdatum",
 		"fieldname": "Belegdatum",
 		"fieldtype": "Date",
+		"width": 100
 	},
 	{
 		"label": "Belegfeld 1",
 		"fieldname": "Belegfeld 1",
 		"fieldtype": "Data",
+		"width": 150
 	},
 	{
 		"label": "Buchungstext",
 		"fieldname": "Buchungstext",
 		"fieldtype": "Text",
+		"width": 300
 	},
 	{
 		"label": "Beleginfo - Art 1",
 		"fieldname": "Beleginfo - Art 1",
 		"fieldtype": "Link",
-		"options": "DocType"
+		"options": "DocType",
+		"width": 100
 	},
 	{
 		"label": "Beleginfo - Inhalt 1",
 		"fieldname": "Beleginfo - Inhalt 1",
 		"fieldtype": "Dynamic Link",
-		"options": "Beleginfo - Art 1"
+		"options": "Beleginfo - Art 1",
+		"width": 150
 	},
 	{
 		"label": "Beleginfo - Art 2",
 		"fieldname": "Beleginfo - Art 2",
 		"fieldtype": "Link",
-		"options": "DocType"
+		"options": "DocType",
+		"width": 100
 	},
 	{
 		"label": "Beleginfo - Inhalt 2",
 		"fieldname": "Beleginfo - Inhalt 2",
 		"fieldtype": "Dynamic Link",
-		"options": "Beleginfo - Art 2"
+		"options": "Beleginfo - Art 2",
+		"width": 150
 	}
 ]
 
diff --git a/erpnext/regional/report/datev/test_datev.py b/erpnext/regional/report/datev/test_datev.py
index 3cc65fe..eed62a8 100644
--- a/erpnext/regional/report/datev/test_datev.py
+++ b/erpnext/regional/report/datev/test_datev.py
@@ -90,7 +90,7 @@
 
 	if not frappe.db.exists("Customer", customer_name):
 		customer = frappe.get_doc({
-			"doctype": "Customer",		
+			"doctype": "Customer",
 			"customer_name": customer_name,
 			"customer_type": "Company",
 			"accounts": [{
@@ -155,17 +155,17 @@
 		setup_fiscal_year()
 
 		warehouse = frappe.db.get_value("Item Default", {
-				"parent": item.name, 
+				"parent": item.name,
 				"company": self.company.name
 			}, "default_warehouse")
 
 		income_account = frappe.db.get_value("Account", {
-				"account_number": "4200", 
+				"account_number": "4200",
 				"company": self.company.name
 			}, "name")
 
 		tax_account = frappe.db.get_value("Account", {
-				"account_number": "3806", 
+				"account_number": "3806",
 				"company": self.company.name
 			}, "name")
 
@@ -186,9 +186,12 @@
 			"charge_type": "On Net Total",
 			"account_head": tax_account,
 			"description": "Umsatzsteuer 19 %",
-			"rate": 19
+			"rate": 19,
+			"cost_center": self.company.cost_center
 		})
 
+		si.cost_center = self.company.cost_center
+
 		si.save()
 		si.submit()
 
@@ -196,7 +199,7 @@
 		def is_subset(get_data, allowed_keys):
 			"""
 			Validate that the dict contains only allowed keys.
-			
+
 			Params:
 			get_data -- Function that returns a list of dicts.
 			allowed_keys -- List of allowed keys
diff --git a/erpnext/regional/report/gstr_1/gstr_1.py b/erpnext/regional/report/gstr_1/gstr_1.py
index 43b1ea8..8885b88 100644
--- a/erpnext/regional/report/gstr_1/gstr_1.py
+++ b/erpnext/regional/report/gstr_1/gstr_1.py
@@ -118,7 +118,7 @@
 				row.append(invoice_details.get(fieldname))
 		taxable_value = 0
 
-		if invoice in self.cgst_igst_invoices:
+		if invoice in self.cgst_sgst_invoices:
 			division_factor = 2
 		else:
 			division_factor = 1
@@ -129,6 +129,8 @@
 					taxable_value += abs(net_amount)
 				elif not self.item_tax_rate.get(invoice):
 					taxable_value += abs(net_amount)
+				elif tax_rate:
+					taxable_value += abs(net_amount)
 
 		row += [tax_rate or 0, taxable_value]
 
@@ -227,7 +229,7 @@
 
 		self.items_based_on_tax_rate = {}
 		self.invoice_cess = frappe._dict()
-		self.cgst_igst_invoices = []
+		self.cgst_sgst_invoices = []
 
 		unidentified_gst_accounts = []
 		for parent, account, item_wise_tax_detail, tax_amount in self.tax_details:
@@ -251,8 +253,8 @@
 							tax_rate = tax_amounts[0]
 							if cgst_or_sgst:
 								tax_rate *= 2
-								if parent not in self.cgst_igst_invoices:
-									self.cgst_igst_invoices.append(parent)
+								if parent not in self.cgst_sgst_invoices:
+									self.cgst_sgst_invoices.append(parent)
 
 							rate_based_dict = self.items_based_on_tax_rate\
 								.setdefault(parent, {}).setdefault(tax_rate, [])
diff --git a/erpnext/regional/report/gstr_2/gstr_2.py b/erpnext/regional/report/gstr_2/gstr_2.py
index f326fe0..f899349 100644
--- a/erpnext/regional/report/gstr_2/gstr_2.py
+++ b/erpnext/regional/report/gstr_2/gstr_2.py
@@ -44,30 +44,30 @@
 		for inv, items_based_on_rate in self.items_based_on_tax_rate.items():
 			invoice_details = self.invoices.get(inv)
 			for rate, items in items_based_on_rate.items():
-				if inv not in self.igst_invoices:
-					rate = rate / 2
-					row, taxable_value = self.get_row_data_for_invoice(inv, invoice_details, rate, items)
-					tax_amount = taxable_value * rate / 100
-					row += [0, tax_amount, tax_amount]
-				else:
-					row, taxable_value = self.get_row_data_for_invoice(inv, invoice_details, rate, items)
-					tax_amount = taxable_value * rate / 100
-					row += [tax_amount, 0, 0]
+				if rate:
+					if inv not in self.igst_invoices:
+						rate = rate / 2
+						row, taxable_value = self.get_row_data_for_invoice(inv, invoice_details, rate, items)
+						tax_amount = taxable_value * rate / 100
+						row += [0, tax_amount, tax_amount]
+					else:
+						row, taxable_value = self.get_row_data_for_invoice(inv, invoice_details, rate, items)
+						tax_amount = taxable_value * rate / 100
+						row += [tax_amount, 0, 0]
 
+					row += [
+						self.invoice_cess.get(inv),
+						invoice_details.get('eligibility_for_itc'),
+						invoice_details.get('itc_integrated_tax'),
+						invoice_details.get('itc_central_tax'),
+						invoice_details.get('itc_state_tax'),
+						invoice_details.get('itc_cess_amount')
+					]
+					if self.filters.get("type_of_business") ==  "CDNR":
+						row.append("Y" if invoice_details.posting_date <= date(2017, 7, 1) else "N")
+						row.append("C" if invoice_details.return_against else "R")
 
-				row += [
-					self.invoice_cess.get(inv),
-					invoice_details.get('eligibility_for_itc'),
-					invoice_details.get('itc_integrated_tax'),
-					invoice_details.get('itc_central_tax'),
-					invoice_details.get('itc_state_tax'),
-					invoice_details.get('itc_cess_amount')
-				]
-				if self.filters.get("type_of_business") ==  "CDNR":
-					row.append("Y" if invoice_details.posting_date <= date(2017, 7, 1) else "N")
-					row.append("C" if invoice_details.return_against else "R")
-
-				self.data.append(row)
+					self.data.append(row)
 
 	def get_igst_invoices(self):
 		self.igst_invoices = []
@@ -86,7 +86,7 @@
 					conditions += opts[1]
 
 		if self.filters.get("type_of_business") ==  "B2B":
-			conditions += "and ifnull(gst_category, '') != 'Overseas' and is_return != 1 "
+			conditions += "and ifnull(gst_category, '') in ('Registered Regular', 'Deemed Export', 'SEZ') and is_return != 1 "
 
 		elif self.filters.get("type_of_business") ==  "CDNR":
 			conditions += """ and is_return = 1 """
diff --git a/erpnext/regional/report/professional_tax_deductions/professional_tax_deductions.py b/erpnext/regional/report/professional_tax_deductions/professional_tax_deductions.py
index 900fe96..acde68a 100644
--- a/erpnext/regional/report/professional_tax_deductions/professional_tax_deductions.py
+++ b/erpnext/regional/report/professional_tax_deductions/professional_tax_deductions.py
@@ -7,8 +7,8 @@
 from erpnext.regional.report.provident_fund_deductions.provident_fund_deductions import get_conditions
 
 def execute(filters=None):
-	columns = get_columns(filters)
 	data = get_data(filters)
+	columns = get_columns(filters) if len(data) else []
 
 	return columns, data
 
@@ -45,6 +45,9 @@
 	component_type_dict = frappe._dict(frappe.db.sql(""" select name, component_type from `tabSalary Component`
 		where component_type = 'Professional Tax' """))
 
+	if not len(component_type_dict):
+		return []
+
 	conditions = get_conditions(filters)
 
 	entry = frappe.db.sql(""" select sal.employee, sal.employee_name, ded.salary_component, ded.amount
diff --git a/erpnext/regional/report/provident_fund_deductions/provident_fund_deductions.py b/erpnext/regional/report/provident_fund_deductions/provident_fund_deductions.py
index 9f58957..597072c 100644
--- a/erpnext/regional/report/provident_fund_deductions/provident_fund_deductions.py
+++ b/erpnext/regional/report/provident_fund_deductions/provident_fund_deductions.py
@@ -3,11 +3,12 @@
 
 from __future__ import unicode_literals
 import frappe
+from frappe.utils import getdate
 from frappe import _
 
 def execute(filters=None):
-	columns = get_columns(filters)
 	data = get_data(filters)
+	columns = get_columns(filters) if len(data) else []
 
 	return columns, data
 
@@ -71,10 +72,13 @@
 		conditions.append("sal.branch = '%s' " % (filters["branch"]) )
 
 	if filters.get("company"):
-		conditions.append("sal.company = '%s' " % (filters["company"]) )
+		conditions.append("sal.company = '%s' " % (filters["company"]))
 
-	if filters.get("period"):
-		conditions.append("month(sal.start_date) = '%s' " % (filters["period"]))
+	if filters.get("month"):
+		conditions.append("month(sal.start_date) = '%s' " % (filters["month"]))
+
+	if filters.get("year"):
+		conditions.append("year(start_date) = '%s' " % (filters["year"]))
 
 	if filters.get("mode_of_payment"):
 		conditions.append("sal.mode_of_payment = '%s' " % (filters["mode_of_payment"]))
@@ -97,7 +101,7 @@
 				"employee": d.employee,
 				"employee_name": d.employee_name,
 				"pf_account": employee_account_dict.get(d.employee),
-				"component_type": d.amount
+				component_type: d.amount
 			})
 
 	return data_list
@@ -114,6 +118,9 @@
 	component_type_dict = frappe._dict(frappe.db.sql(""" select name, component_type from `tabSalary Component`
 		where component_type in ('Provident Fund', 'Additional Provident Fund', 'Provident Fund Loan')"""))
 
+	if not len(component_type_dict):
+		return []
+
 	entry = frappe.db.sql(""" select sal.name, sal.employee, sal.employee_name, ded.salary_component, ded.amount
 		from `tabSalary Slip` sal, `tabSalary Detail` ded
 		where sal.name = ded.parent
@@ -150,4 +157,12 @@
 
 			data.append(employee)
 
-	return data
\ No newline at end of file
+	return data
+
+@frappe.whitelist()
+def get_years():
+	year_list = frappe.db.sql_list("""select distinct YEAR(end_date) from `tabSalary Slip` ORDER BY YEAR(end_date) DESC""")
+	if not year_list:
+		year_list = [getdate().year]
+
+	return "\n".join(str(year) for year in year_list)
\ No newline at end of file
diff --git a/erpnext/regional/united_arab_emirates/utils.py b/erpnext/regional/united_arab_emirates/utils.py
index 772bbf5..a0425f6 100644
--- a/erpnext/regional/united_arab_emirates/utils.py
+++ b/erpnext/regional/united_arab_emirates/utils.py
@@ -11,14 +11,17 @@
 
 	for row in doc.items:
 		tax_rate = 0.0
-		item_tax_rate = frappe.parse_json(row.item_tax_rate)
+		item_tax_rate = 0.0
+
+		if row.item_tax_rate:
+			item_tax_rate = frappe.parse_json(row.item_tax_rate)
 
 		# First check if tax rate is present
 		# If not then look up in item_wise_tax_detail
 		if item_tax_rate:
 			for account, rate in iteritems(item_tax_rate):
 				tax_rate += rate
-		elif itemised_tax.get(row.item_code):
+		elif row.item_code and itemised_tax.get(row.item_code):
 			tax_rate = sum([tax.get('tax_rate', 0) for d, tax in itemised_tax.get(row.item_code).items()])
 
 		row.tax_rate = flt(tax_rate, row.precision("tax_rate"))
diff --git a/erpnext/regional/united_states/setup.py b/erpnext/regional/united_states/setup.py
index cae28be..2b0ecaf 100644
--- a/erpnext/regional/united_states/setup.py
+++ b/erpnext/regional/united_states/setup.py
@@ -14,6 +14,22 @@
 		'Supplier': [
 			dict(fieldname='irs_1099', fieldtype='Check', insert_after='tax_id',
 				label='Is IRS 1099 reporting required for supplier?')
+		],
+		'Sales Order': [
+			dict(fieldname='exempt_from_sales_tax', fieldtype='Check', insert_after='taxes_and_charges',
+				label='Is customer exempted from sales tax?')
+		],
+		'Sales Invoice': [
+			dict(fieldname='exempt_from_sales_tax', fieldtype='Check', insert_after='taxes_section',
+				label='Is customer exempted from sales tax?')
+		],
+		'Customer': [
+			dict(fieldname='exempt_from_sales_tax', fieldtype='Check', insert_after='represents_company',
+				label='Is customer exempted from sales tax?')
+		],
+		'Quotation': [
+			dict(fieldname='exempt_from_sales_tax', fieldtype='Check', insert_after='taxes_and_charges',
+				label='Is customer exempted from sales tax?')
 		]
 	}
 	create_custom_fields(custom_fields, update=update)
diff --git a/erpnext/restaurant/doctype/restaurant_order_entry/restaurant_order_entry.py b/erpnext/restaurant/doctype/restaurant_order_entry/restaurant_order_entry.py
index a748f9a..357deaa 100644
--- a/erpnext/restaurant/doctype/restaurant_order_entry/restaurant_order_entry.py
+++ b/erpnext/restaurant/doctype/restaurant_order_entry/restaurant_order_entry.py
@@ -65,6 +65,7 @@
 
 	return invoice.name
 
+@frappe.whitelist()
 def item_query_restaurant(doctype='Item', txt='', searchfield='name', start=0, page_len=20, filters=None, as_dict=False):
 	'''Return items that are selected in active menu of the restaurant'''
 	restaurant, menu = get_restaurant_and_menu_name(filters['table'])
@@ -84,4 +85,4 @@
 	if not menu:
 		frappe.throw(_('Please set an active menu for Restaurant {0}').format(restaurant))
 
-	return restaurant, menu
\ No newline at end of file
+	return restaurant, menu
diff --git a/erpnext/selling/dashboard_chart/item_wise_annual_sales/item_wise_annual_sales.json b/erpnext/selling/dashboard_chart/item_wise_annual_sales/item_wise_annual_sales.json
new file mode 100644
index 0000000..290e526
--- /dev/null
+++ b/erpnext/selling/dashboard_chart/item_wise_annual_sales/item_wise_annual_sales.json
@@ -0,0 +1,24 @@
+{
+ "chart_name": "Item-wise Annual Sales",
+ "chart_type": "Report",
+ "creation": "2020-07-20 20:17:16.474566",
+ "custom_options": "",
+ "docstatus": 0,
+ "doctype": "Dashboard Chart",
+ "dynamic_filters_json": "{\"company\":\"frappe.defaults.get_user_default(\\\"Company\\\")\",\"to_date\":\"frappe.datetime.nowdate()\"}",
+ "filters_json": "{\"from_date\":\"2020-06-22\"}",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "modified": "2020-07-22 14:42:25.512675",
+ "modified_by": "Administrator",
+ "module": "Selling",
+ "name": "Item-wise Annual Sales",
+ "number_of_groups": 0,
+ "owner": "Administrator",
+ "report_name": "Item-wise Sales History",
+ "timeseries": 0,
+ "type": "Bar",
+ "use_report_chart": 1,
+ "y_axis": []
+}
\ No newline at end of file
diff --git a/erpnext/selling/dashboard_chart/sales_order_analysis/sales_order_analysis.json b/erpnext/selling/dashboard_chart/sales_order_analysis/sales_order_analysis.json
new file mode 100644
index 0000000..5e1a0d9
--- /dev/null
+++ b/erpnext/selling/dashboard_chart/sales_order_analysis/sales_order_analysis.json
@@ -0,0 +1,24 @@
+{
+ "chart_name": "Sales Order Analysis",
+ "chart_type": "Report",
+ "creation": "2020-07-20 20:17:16.440393",
+ "custom_options": "{\"type\": \"donut\", \"height\": 300, \"axisOptions\": {\"shortenYAxisNumbers\": 1}}",
+ "docstatus": 0,
+ "doctype": "Dashboard Chart",
+ "dynamic_filters_json": "{\"company\":\"frappe.defaults.get_user_default(\\\"Company\\\")\",\"to_date\":\"frappe.datetime.nowdate()\"}",
+ "filters_json": "{\"status\":[\"To Bill\",\"To Deliver\"],\"group_by_so\":0,\"from_date\":\"2020-06-22\"}",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "modified": "2020-07-22 17:06:05.750660",
+ "modified_by": "Administrator",
+ "module": "Selling",
+ "name": "Sales Order Analysis",
+ "number_of_groups": 0,
+ "owner": "Administrator",
+ "report_name": "Sales Order Analysis",
+ "timeseries": 0,
+ "type": "Donut",
+ "use_report_chart": 1,
+ "y_axis": []
+}
\ No newline at end of file
diff --git a/erpnext/selling/dashboard_chart/sales_order_trends/sales_order_trends.json b/erpnext/selling/dashboard_chart/sales_order_trends/sales_order_trends.json
new file mode 100644
index 0000000..914d915
--- /dev/null
+++ b/erpnext/selling/dashboard_chart/sales_order_trends/sales_order_trends.json
@@ -0,0 +1,24 @@
+{
+ "chart_name": "Sales Order Trends",
+ "chart_type": "Report",
+ "creation": "2020-07-20 20:17:16.508240",
+ "custom_options": "{\"type\": \"line\", \"axisOptions\": {\"shortenYAxisNumbers\": 1}, \"tooltipOptions\": {}, \"lineOptions\": {\"regionFill\": 1}}",
+ "docstatus": 0,
+ "doctype": "Dashboard Chart",
+ "dynamic_filters_json": "{\"company\":\"frappe.defaults.get_user_default(\\\"Company\\\")\",\"fiscal_year\":\"frappe.sys_defaults.fiscal_year\"}",
+ "filters_json": "{\"period\":\"Monthly\",\"based_on\":\"Item\"}",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "modified": "2020-07-22 16:24:45.726270",
+ "modified_by": "Administrator",
+ "module": "Selling",
+ "name": "Sales Order Trends",
+ "number_of_groups": 0,
+ "owner": "Administrator",
+ "report_name": "Sales Order Trends",
+ "timeseries": 0,
+ "type": "Line",
+ "use_report_chart": 1,
+ "y_axis": []
+}
\ No newline at end of file
diff --git a/erpnext/selling/dashboard_chart/top_customers/top_customers.json b/erpnext/selling/dashboard_chart/top_customers/top_customers.json
new file mode 100644
index 0000000..59a2ba3
--- /dev/null
+++ b/erpnext/selling/dashboard_chart/top_customers/top_customers.json
@@ -0,0 +1,24 @@
+{
+ "chart_name": "Top Customers",
+ "chart_type": "Report",
+ "creation": "2020-07-20 20:17:16.539281",
+ "custom_options": "",
+ "docstatus": 0,
+ "doctype": "Dashboard Chart",
+ "dynamic_filters_json": "{\"company\":\"frappe.defaults.get_user_default(\\\"Company\\\")\",\"fiscal_year\":\"frappe.sys_defaults.fiscal_year\"}",
+ "filters_json": "{\"period\":\"Yearly\",\"based_on\":\"Customer\"}",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "modified": "2020-07-22 17:03:10.320147",
+ "modified_by": "Administrator",
+ "module": "Selling",
+ "name": "Top Customers",
+ "number_of_groups": 0,
+ "owner": "Administrator",
+ "report_name": "Delivery Note Trends",
+ "timeseries": 0,
+ "type": "Bar",
+ "use_report_chart": 1,
+ "y_axis": []
+}
\ No newline at end of file
diff --git a/erpnext/selling/dashboard_fixtures.py b/erpnext/selling/dashboard_fixtures.py
deleted file mode 100644
index 889cb88..0000000
--- a/erpnext/selling/dashboard_fixtures.py
+++ /dev/null
@@ -1,198 +0,0 @@
-# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-import frappe
-import json
-from frappe import _
-from frappe.utils import nowdate
-from erpnext.accounts.utils import get_fiscal_year
-
-def get_data():
-	return frappe._dict({
-		"dashboards": get_dashboards(),
-		"charts": get_charts(),
-		"number_cards": get_number_cards(),
-	})
-
-def get_company_for_dashboards():
-	company = frappe.defaults.get_defaults().company
-	if company:
-		return company
-	else:
-		company_list = frappe.get_list("Company")
-		if company_list:
-			return company_list[0].name
-	return None
-
-company = frappe.get_doc("Company", get_company_for_dashboards())
-fiscal_year = get_fiscal_year(nowdate(), as_dict=1)
-fiscal_year_name = fiscal_year.get("name")
-start_date = str(fiscal_year.get("year_start_date"))
-end_date = str(fiscal_year.get("year_end_date"))
-
-def get_dashboards():
-	return [{
-		"name": "Selling",
-		"dashboard_name": "Selling",
-		"charts": [
-			{ "chart": "Sales Order Trends", "width": "Full"},
-			{ "chart": "Top Customers", "width": "Half"},
-			{ "chart": "Sales Order Analysis", "width": "Half"},
-			{ "chart": "Item-wise Annual Sales", "width": "Full"}
-		],
-		"cards": [
-			{ "card": "Annual Sales"},
-			{ "card": "Sales Orders to Deliver"},
-			{ "card": "Sales Orders to Bill"},
-			{ "card": "Active Customers"}
-		]
-	}]
-
-def get_charts():
-	return [
-		{
-			"name": "Sales Order Analysis",
-			"chart_name": _("Sales Order Analysis"),
-			"chart_type": "Report",
-			"custom_options": json.dumps({
-				"type": "donut",
-				"height": 300,
-				"axisOptions": {"shortenYAxisNumbers": 1}
-			}),
-			"doctype": "Dashboard Chart",
-			"filters_json": json.dumps({
-				"company": company.name,
-				"from_date": start_date,
-				"to_date": end_date
-			}),
-			"is_custom": 1,
-			"is_public": 1,
-			"owner": "Administrator",
-			"report_name": "Sales Order Analysis",
-			"type": "Donut"
-		},
-		{
-			"name": "Item-wise Annual Sales",
-			"chart_name": _("Item-wise Annual Sales"),
-			"chart_type": "Report",
-			"doctype": "Dashboard Chart",
-			"filters_json": json.dumps({
-				"company": company.name,
-				"from_date": start_date,
-				"to_date": end_date
-			}),
-			"is_custom": 1,
-			"is_public": 1,
-			"owner": "Administrator",
-			"report_name": "Item-wise Sales History",
-			"type": "Bar"
-		},
-		{
-			"name": "Sales Order Trends",
-			"chart_name": _("Sales Order Trends"),
-			"chart_type": "Report",
-			"custom_options": json.dumps({
-				"type": "line",
-				"axisOptions": {"shortenYAxisNumbers": 1},
-				"tooltipOptions": {},
-				"lineOptions": {
-					"regionFill": 1
-				}
-			}),
-			"doctype": "Dashboard Chart",
-			"filters_json": json.dumps({
-				"company": company.name,
-				"period": "Monthly",
-				"fiscal_year": fiscal_year_name,
-				"based_on": "Item"
-			}),
-			"is_custom": 1,
-			"is_public": 1,
-			"owner": "Administrator",
-			"report_name": "Sales Order Trends",
-			"type": "Line"
-		},
-		{
-			"name": "Top Customers",
-			"chart_name": _("Top Customers"),
-			"chart_type": "Report",
-			"doctype": "Dashboard Chart",
-			"filters_json": json.dumps({
-				"company": company.name,
-				"period": "Monthly",
-				"fiscal_year": fiscal_year_name,
-				"based_on": "Customer"
-			}),
-			"is_custom": 1,
-			"is_public": 1,
-			"owner": "Administrator",
-			"report_name": "Delivery Note Trends",
-			"type": "Bar"
-		}
- 	]
-
-def get_number_cards():
-	return [
-		{
-			"name": "Annual Sales",
-			"aggregate_function_based_on": "base_net_total",
-			"doctype": "Number Card",
-			"document_type": "Sales Order",
-			"filters_json": json.dumps([
-				["Sales Order", "transaction_date", "Between", [start_date, end_date], False],
-				["Sales Order", "status", "not in", ["Draft", "Cancelled", "Closed", None], False],
-				["Sales Order", "docstatus", "=", 1, False],
-				["Sales Order", "company", "=", company.name, False]
-			]),
-			"function": "Sum",
-			"is_public": 1,
-			"label": _("Annual Sales"),
-			"owner": "Administrator",
-			"show_percentage_stats": 1,
-			"stats_time_interval": "Monthly"
-		},
-		{
-			"name": "Sales Orders to Deliver",
-			"doctype": "Number Card",
-			"document_type": "Sales Order",
-			"filters_json": json.dumps([
-				["Sales Order", "status", "in", ["To Deliver and Bill", "To Deliver", None], False],
-				["Sales Order", "docstatus", "=", 1, False],
-				["Sales Order", "company", "=", company.name, False]
-			]),
-			"function": "Count",
-			"is_public": 1,
-			"label": _("Sales Orders to Deliver"),
-			"owner": "Administrator",
-			"show_percentage_stats": 1,
-			"stats_time_interval": "Weekly"
-		},
-		{
-			"name": "Sales Orders to Bill",
-			"doctype": "Number Card",
-			"document_type": "Sales Order",
-			"filters_json": json.dumps([
-				["Sales Order", "status", "in", ["To Deliver and Bill", "To Bill", None], False],
-				["Sales Order", "docstatus", "=", 1, False],
-				["Sales Order", "company", "=", company.name, False]
-			]),
-			"function": "Count",
-			"is_public": 1,
-			"label": _("Sales Orders to Bill"),
-			"owner": "Administrator",
-			"show_percentage_stats": 1,
-			"stats_time_interval": "Weekly"
-		},
-		{
-			"name": "Active Customers",
-			"doctype": "Number Card",
-			"document_type": "Customer",
-			"filters_json": json.dumps([["Customer", "disabled", "=", "0"]]),
-			"function": "Count",
-			"is_public": 1,
-			"label": "Active Customers",
-			"owner": "Administrator",
-			"show_percentage_stats": 1,
-			"stats_time_interval": "Monthly"
-		}
-	]
\ No newline at end of file
diff --git a/erpnext/selling/desk_page/selling/selling.json b/erpnext/selling/desk_page/selling/selling.json
index 60b1532..2252382 100644
--- a/erpnext/selling/desk_page/selling/selling.json
+++ b/erpnext/selling/desk_page/selling/selling.json
@@ -23,7 +23,7 @@
   {
    "hidden": 0,
    "label": "Other Reports",
-   "links": "[\n    {\n        \"dependencies\": [\n            \"Lead\"\n        ],\n        \"doctype\": \"Lead\",\n        \"is_query_report\": true,\n        \"label\": \"Lead Details\",\n        \"name\": \"Lead Details\",\n        \"type\": \"report\"\n    },\n    {\n        \"dependencies\": [\n            \"Address\"\n        ],\n        \"doctype\": \"Address\",\n        \"is_query_report\": true,\n        \"label\": \"Customer Addresses And Contacts\",\n        \"name\": \"Address And Contacts\",\n        \"route_options\": {\n            \"party_type\": \"Customer\"\n        },\n        \"type\": \"report\"\n    },\n    {\n        \"dependencies\": [\n            \"Item\"\n        ],\n        \"doctype\": \"Item\",\n        \"is_query_report\": true,\n        \"label\": \"Available Stock for Packing Items\",\n        \"name\": \"Available Stock for Packing Items\",\n        \"type\": \"report\"\n    },\n    {\n        \"dependencies\": [\n            \"Sales Order\"\n        ],\n        \"doctype\": \"Sales Order\",\n        \"is_query_report\": true,\n        \"label\": \"Pending SO Items For Purchase Request\",\n        \"name\": \"Pending SO Items For Purchase Request\",\n        \"type\": \"report\"\n    },\n    {\n        \"dependencies\": [\n            \"Customer\"\n        ],\n        \"doctype\": \"Customer\",\n        \"is_query_report\": true,\n        \"label\": \"Customer Credit Balance\",\n        \"name\": \"Customer Credit Balance\",\n        \"type\": \"report\"\n    },\n    {\n        \"dependencies\": [\n            \"Customer\"\n        ],\n        \"doctype\": \"Customer\",\n        \"is_query_report\": true,\n        \"label\": \"Customers Without Any Sales Transactions\",\n        \"name\": \"Customers Without Any Sales Transactions\",\n        \"type\": \"report\"\n    },\n    {\n        \"dependencies\": [\n            \"Customer\"\n        ],\n        \"doctype\": \"Customer\",\n        \"is_query_report\": true,\n        \"label\": \"Sales Partners Commission\",\n        \"name\": \"Sales Partners Commission\",\n        \"type\": \"report\"\n    }\n]"
+   "links": "[\n    {\n        \"dependencies\": [\n            \"Lead\"\n        ],\n        \"doctype\": \"Lead\",\n        \"is_query_report\": true,\n        \"label\": \"Lead Details\",\n        \"name\": \"Lead Details\",\n        \"type\": \"report\"\n    },\n    {\n        \"dependencies\": [\n            \"Address\"\n        ],\n        \"doctype\": \"Address\",\n        \"is_query_report\": true,\n        \"label\": \"Customer Addresses And Contacts\",\n        \"name\": \"Address And Contacts\",\n        \"route_options\": {\n            \"party_type\": \"Customer\"\n        },\n        \"type\": \"report\"\n    },\n    {\n        \"dependencies\": [\n            \"Item\"\n        ],\n        \"doctype\": \"Item\",\n        \"is_query_report\": true,\n        \"label\": \"Available Stock for Packing Items\",\n        \"name\": \"Available Stock for Packing Items\",\n        \"type\": \"report\"\n    },\n    {\n        \"dependencies\": [\n            \"Sales Order\"\n        ],\n        \"doctype\": \"Sales Order\",\n        \"is_query_report\": true,\n        \"label\": \"Pending SO Items For Purchase Request\",\n        \"name\": \"Pending SO Items For Purchase Request\",\n        \"type\": \"report\"\n    },\n     {\n        \"dependencies\": [\n            \"Delivery Note\"\n        ],\n        \"doctype\": \"Delivery Note\",\n        \"is_query_report\": true,\n        \"label\": \"Delivery Note Trends\",\n        \"name\": \"Delivery Note Trends\",\n        \"type\": \"report\"\n    },\n    {\n        \"dependencies\": [\n            \"Sales Invoice\"\n        ],\n        \"doctype\": \"Sales Invoice\",\n        \"is_query_report\": true,\n        \"label\": \"Sales Invoice Trends\",\n        \"name\": \"Sales Invoice Trends\",\n        \"type\": \"report\"\n    },\n    {\n        \"dependencies\": [\n            \"Customer\"\n        ],\n        \"doctype\": \"Customer\",\n        \"is_query_report\": true,\n        \"label\": \"Customer Credit Balance\",\n        \"name\": \"Customer Credit Balance\",\n        \"type\": \"report\"\n    },\n    {\n        \"dependencies\": [\n            \"Customer\"\n        ],\n        \"doctype\": \"Customer\",\n        \"is_query_report\": true,\n        \"label\": \"Customers Without Any Sales Transactions\",\n        \"name\": \"Customers Without Any Sales Transactions\",\n        \"type\": \"report\"\n    },\n    {\n        \"dependencies\": [\n            \"Customer\"\n        ],\n        \"doctype\": \"Customer\",\n        \"is_query_report\": true,\n        \"label\": \"Sales Partners Commission\",\n        \"name\": \"Sales Partners Commission\",\n        \"type\": \"report\"\n    }\n]"
   }
  ],
  "category": "Modules",
@@ -44,7 +44,7 @@
  "idx": 0,
  "is_standard": 1,
  "label": "Selling",
- "modified": "2020-06-19 13:23:24.861706",
+ "modified": "2020-06-29 19:26:35.139097",
  "modified_by": "Administrator",
  "module": "Selling",
  "name": "Selling",
diff --git a/erpnext/selling/doctype/customer/customer.py b/erpnext/selling/doctype/customer/customer.py
index 682dfed..e614acd 100644
--- a/erpnext/selling/doctype/customer/customer.py
+++ b/erpnext/selling/doctype/customer/customer.py
@@ -342,11 +342,10 @@
 @frappe.whitelist()
 def get_customer_list(doctype, txt, searchfield, start, page_len, filters=None):
 	from erpnext.controllers.queries import get_fields
+	fields = ["name", "customer_name", "customer_group", "territory"]
 
 	if frappe.db.get_default("cust_master_name") == "Customer Name":
 		fields = ["name", "customer_group", "territory"]
-	else:
-		fields = ["name", "customer_name", "customer_group", "territory"]
 
 	fields = get_fields("Customer", fields)
 
@@ -388,8 +387,7 @@
 			credit_controller_users = get_users_with_role(credit_controller_role or "Sales Master Manager")
 
 			# form a list of emails and names to show to the user
-			credit_controller_users_list = [user for user in credit_controller_users if frappe.db.exists("Employee", {"prefered_email": user})]
-			credit_controller_users = [get_formatted_email(user).replace("<", "(").replace(">", ")") for user in credit_controller_users_list]
+			credit_controller_users = [get_formatted_email(user).replace("<", "(").replace(">", ")") for user in credit_controller_users]
 
 			if not credit_controller_users:
 				frappe.throw(_("Please contact your administrator to extend the credit limits for {0}.".format(customer)))
@@ -409,7 +407,7 @@
 						'customer': customer,
 						'customer_outstanding': customer_outstanding,
 						'credit_limit': credit_limit,
-						'credit_controller_users_list': credit_controller_users_list
+						'credit_controller_users_list': credit_controller_users
 					}
 				}
 			)
@@ -543,6 +541,7 @@
 
 	return address
 
+@frappe.whitelist()
 def get_customer_primary_contact(doctype, txt, searchfield, start, page_len, filters):
 	customer = filters.get('customer')
 	return frappe.db.sql("""
@@ -553,4 +552,4 @@
 		""", {
 			'customer': customer,
 			'txt': '%%%s%%' % txt
-		})
+		})
\ No newline at end of file
diff --git a/erpnext/selling/doctype/pos_closing_voucher/pos_closing_voucher.js b/erpnext/selling/doctype/pos_closing_voucher/pos_closing_voucher.js
deleted file mode 100644
index f24caf7..0000000
--- a/erpnext/selling/doctype/pos_closing_voucher/pos_closing_voucher.js
+++ /dev/null
@@ -1,87 +0,0 @@
-// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
-// For license information, please see license.txt
-
-frappe.ui.form.on('POS Closing Voucher', {
-	onload: function(frm) {
-		frm.set_query("pos_profile", function(doc) {
-			return {
-				filters: {
-					'user': doc.user
-				}
-			};
-		});
-
-		frm.set_query("user", function(doc) {
-			return {
-				query: "erpnext.selling.doctype.pos_closing_voucher.pos_closing_voucher.get_cashiers",
-				filters: {
-					'parent': doc.pos_profile
-				}
-			};
-		});
-	},
-
-	total_amount: function(frm) {
-		get_difference_amount(frm);
-	},
-	custody_amount: function(frm){
-		get_difference_amount(frm);
-	},
-	expense_amount: function(frm){
-		get_difference_amount(frm);
-	},
-	refresh: function(frm) {
-		get_closing_voucher_details(frm);
-	},
-	period_start_date: function(frm) {
-		get_closing_voucher_details(frm);
-	},
-	period_end_date: function(frm) {
-		get_closing_voucher_details(frm);
-	},
-	company: function(frm) {
-		get_closing_voucher_details(frm);
-	},
-	pos_profile: function(frm) {
-		get_closing_voucher_details(frm);
-	},
-	user: function(frm) {
-		get_closing_voucher_details(frm);
-	},
-});
-
-frappe.ui.form.on('POS Closing Voucher Details', {
-	collected_amount: function(doc, cdt, cdn) {
-		var row = locals[cdt][cdn];
-		frappe.model.set_value(cdt, cdn, "difference", row.collected_amount - row.expected_amount);
-	}
-});
-
-var get_difference_amount = function(frm){
-	frm.doc.difference = frm.doc.total_amount - frm.doc.custody_amount - frm.doc.expense_amount;
-	refresh_field("difference");
-};
-
-var get_closing_voucher_details = function(frm) {
-	if (frm.doc.period_end_date && frm.doc.period_start_date && frm.doc.company && frm.doc.pos_profile && frm.doc.user) {
-		frappe.call({
-			method: "get_closing_voucher_details",
-			doc: frm.doc,
-			callback: function(r) {
-				if (r.message) {
-					refresh_field("payment_reconciliation");
-					refresh_field("sales_invoices_summary");
-					refresh_field("taxes");
-
-					refresh_field("grand_total");
-					refresh_field("net_total");
-					refresh_field("total_quantity");
-					refresh_field("total_amount");
-
-					frm.get_field("payment_reconciliation_details").$wrapper.html(r.message);
-				}
-			}
-		});
-	}
-
-};
diff --git a/erpnext/selling/doctype/pos_closing_voucher/pos_closing_voucher.json b/erpnext/selling/doctype/pos_closing_voucher/pos_closing_voucher.json
deleted file mode 100644
index 2ac5779..0000000
--- a/erpnext/selling/doctype/pos_closing_voucher/pos_closing_voucher.json
+++ /dev/null
@@ -1,1016 +0,0 @@
-{
- "allow_copy": 0, 
- "allow_events_in_timeline": 0, 
- "allow_guest_to_view": 0, 
- "allow_import": 0, 
- "allow_rename": 0, 
- "autoname": "POS-CLO-.YYYY.-.#####", 
- "beta": 0, 
- "creation": "2018-05-28 19:06:40.830043", 
- "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, 
-   "default": "Today", 
-   "fieldname": "period_start_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": "Period Start Date", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 1, 
-   "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, 
-   "default": "Today", 
-   "fieldname": "period_end_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": "Period End 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": 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, 
-   "fieldname": "column_break_3", 
-   "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
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "default": "Today", 
-   "fieldname": "posting_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": "Posting 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
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "section_break_5", 
-   "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": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "company", 
-   "fieldtype": "Link", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_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": 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, 
-   "fieldname": "column_break_7", 
-   "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
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "pos_profile", 
-   "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": "POS Profile", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "POS Profile", 
-   "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
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "default": "", 
-   "fieldname": "user", 
-   "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": "Cashier", 
-   "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": 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, 
-   "fieldname": "expense_details_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": "Expense Details", 
-   "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, 
-   "fieldname": "expense_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": "Expense 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
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "custody_amount", 
-   "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": "Amount in Custody", 
-   "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, 
-   "fieldname": "column_break_13", 
-   "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
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 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 Collected 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
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "difference", 
-   "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": "Difference", 
-   "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, 
-   "fieldname": "section_break_9", 
-   "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": 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, 
-   "fieldname": "payment_reconciliation_details", 
-   "fieldtype": "HTML", 
-   "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": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "section_break_11", 
-   "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": "Modes of Payment", 
-   "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, 
-   "fieldname": "payment_reconciliation", 
-   "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 Reconciliation", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "POS Closing Voucher Details", 
-   "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": 1, 
-   "columns": 0, 
-   "fieldname": "section_break_13", 
-   "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": "Details", 
-   "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, 
-   "fieldname": "grand_total", 
-   "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": "Grand Total", 
-   "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, 
-   "fieldname": "net_total", 
-   "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": "Net Total", 
-   "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, 
-   "fieldname": "total_quantity", 
-   "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": "Total Quantity", 
-   "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, 
-   "fieldname": "column_break_16", 
-   "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, 
-   "label": "Taxes", 
-   "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, 
-   "fieldname": "taxes", 
-   "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": "Taxes", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "POS Closing Voucher Taxes", 
-   "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": 1, 
-   "columns": 0, 
-   "fieldname": "section_break_12", 
-   "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": "Linked Invoices", 
-   "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, 
-   "fieldname": "sales_invoices_summary", 
-   "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": "Sales Invoices Summary", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "POS Closing Voucher Invoices", 
-   "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, 
-   "fieldname": "section_break_14", 
-   "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": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 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": "POS Closing Voucher", 
-   "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
-  }
- ], 
- "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-01-28 12:33:45.217813", 
- "modified_by": "Administrator", 
- "module": "Selling", 
- "name": "POS Closing Voucher", 
- "name_case": "", 
- "owner": "Administrator", 
- "permissions": [
-  {
-   "amend": 0, 
-   "cancel": 0, 
-   "create": 1, 
-   "delete": 0, 
-   "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": 0, 
-   "email": 1, 
-   "export": 1, 
-   "if_owner": 0, 
-   "import": 0, 
-   "permlevel": 0, 
-   "print": 1, 
-   "read": 1, 
-   "report": 1, 
-   "role": "Sales Manager", 
-   "set_user_permissions": 0, 
-   "share": 1, 
-   "submit": 0, 
-   "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
-}
\ No newline at end of file
diff --git a/erpnext/selling/doctype/pos_closing_voucher/pos_closing_voucher.py b/erpnext/selling/doctype/pos_closing_voucher/pos_closing_voucher.py
deleted file mode 100644
index bb5f83e..0000000
--- a/erpnext/selling/doctype/pos_closing_voucher/pos_closing_voucher.py
+++ /dev/null
@@ -1,188 +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 import _
-from frappe.model.document import Document
-from collections import defaultdict
-from erpnext.controllers.taxes_and_totals import get_itemised_tax_breakup_data
-import json
-
-class POSClosingVoucher(Document):
-	def get_closing_voucher_details(self):
-		filters = {
-			'doc': self.name,
-			'from_date': self.period_start_date,
-			'to_date': self.period_end_date,
-			'company': self.company,
-			'pos_profile': self.pos_profile,
-			'user': self.user,
-			'is_pos': 1
-		}
-
-		invoice_list = get_invoices(filters)
-		self.set_invoice_list(invoice_list)
-
-		sales_summary = get_sales_summary(invoice_list)
-		self.set_sales_summary_values(sales_summary)
-		self.total_amount = sales_summary['grand_total']
-
-		if not self.get('payment_reconciliation'):
-			mop = get_mode_of_payment_details(invoice_list)
-			self.set_mode_of_payments(mop)
-
-		taxes = get_tax_details(invoice_list)
-		self.set_taxes(taxes)
-
-		return self.get_payment_reconciliation_details()
-
-	def validate(self):
-		user = frappe.get_all('POS Closing Voucher',
-			filters = {
-				'user': self.user,
-				'docstatus': 1
-			},
-			or_filters = {
-					'period_start_date': ('between', [self.period_start_date, self.period_end_date]),
-					'period_end_date': ('between', [self.period_start_date, self.period_end_date])
-			})
-
-		if user:
-			frappe.throw(_("POS Closing Voucher alreday exists for {0} between date {1} and {2}")
-				.format(self.user, self.period_start_date, self.period_end_date))
-
-	def set_invoice_list(self, invoice_list):
-		self.sales_invoices_summary = []
-		for invoice in invoice_list:
-			self.append('sales_invoices_summary', {
-				'invoice': invoice['name'],
-				'qty_of_items': invoice['pos_total_qty'],
-				'grand_total': invoice['grand_total']
-			})
-
-	def set_sales_summary_values(self, sales_summary):
-		self.grand_total = sales_summary['grand_total']
-		self.net_total = sales_summary['net_total']
-		self.total_quantity = sales_summary['total_qty']
-
-	def set_mode_of_payments(self, mop):
-		self.payment_reconciliation = []
-		for m in mop:
-			self.append('payment_reconciliation', {
-				'mode_of_payment': m['name'],
-				'expected_amount': m['amount']
-			})
-
-	def set_taxes(self, taxes):
-		self.taxes = []
-		for tax in taxes:
-			self.append('taxes', {
-				'rate': tax['rate'],
-				'amount': tax['amount']
-			})
-
-	def get_payment_reconciliation_details(self):
-		currency = get_company_currency(self)
-		return frappe.render_template("erpnext/selling/doctype/pos_closing_voucher/closing_voucher_details.html",
-			{"data": self, "currency": currency})
-
-@frappe.whitelist()
-def get_cashiers(doctype, txt, searchfield, start, page_len, filters):
-	cashiers_list = frappe.get_all("POS Profile User", filters=filters, fields=['user'])
-	cashiers = [cashier for cashier in set(c['user'] for c in cashiers_list)]
-	return [[c] for c in cashiers]
-
-def get_mode_of_payment_details(invoice_list):
-	mode_of_payment_details = []
-	invoice_list_names = ",".join(['"' + invoice['name'] + '"' for invoice in invoice_list])
-	if invoice_list:
-		inv_mop_detail = frappe.db.sql("""select a.owner, a.posting_date,
-			ifnull(b.mode_of_payment, '') as mode_of_payment, sum(b.base_amount) as paid_amount
-			from `tabSales Invoice` a, `tabSales Invoice Payment` b
-			where a.name = b.parent
-			and a.name in ({invoice_list_names})
-			group by a.owner, a.posting_date, mode_of_payment
-			union
-			select a.owner,a.posting_date,
-			ifnull(b.mode_of_payment, '') as mode_of_payment, sum(b.base_paid_amount) as paid_amount
-			from `tabSales Invoice` a, `tabPayment Entry` b,`tabPayment Entry Reference` c
-			where a.name = c.reference_name
-			and b.name = c.parent
-			and a.name in ({invoice_list_names})
-			group by a.owner, a.posting_date, mode_of_payment
-			union
-			select a.owner, a.posting_date,
-			ifnull(a.voucher_type,'') as mode_of_payment, sum(b.credit)
-			from `tabJournal Entry` a, `tabJournal Entry Account` b
-			where a.name = b.parent
-			and a.docstatus = 1
-			and b.reference_type = "Sales Invoice"
-			and b.reference_name in ({invoice_list_names})
-			group by a.owner, a.posting_date, mode_of_payment
-			""".format(invoice_list_names=invoice_list_names), as_dict=1)
-
-		inv_change_amount = frappe.db.sql("""select a.owner, a.posting_date,
-			ifnull(b.mode_of_payment, '') as mode_of_payment, sum(a.base_change_amount) as change_amount
-			from `tabSales Invoice` a, `tabSales Invoice Payment` b
-			where a.name = b.parent
-			and a.name in ({invoice_list_names})
-			and b.mode_of_payment = 'Cash'
-			and a.base_change_amount > 0
-			group by a.owner, a.posting_date, mode_of_payment""".format(invoice_list_names=invoice_list_names), as_dict=1)
-
-		for d in inv_change_amount:
-			for det in inv_mop_detail:
-				if det["owner"] == d["owner"] and det["posting_date"] == d["posting_date"] and det["mode_of_payment"] == d["mode_of_payment"]:
-					paid_amount = det["paid_amount"] - d["change_amount"]
-					det["paid_amount"] = paid_amount
-
-		payment_details = defaultdict(int)
-		for d in inv_mop_detail:
-			payment_details[d.mode_of_payment] += d.paid_amount
-
-		for m in payment_details:
-			mode_of_payment_details.append({'name': m, 'amount': payment_details[m]})
-
-	return mode_of_payment_details
-
-def get_tax_details(invoice_list):
-	tax_breakup = []
-	tax_details = defaultdict(int)
-	for invoice in invoice_list:
-		doc = frappe.get_doc("Sales Invoice", invoice.name)
-		itemised_tax, itemised_taxable_amount = get_itemised_tax_breakup_data(doc)
-
-		if itemised_tax:
-			for a in itemised_tax:
-				for b in itemised_tax[a]:
-					for c in itemised_tax[a][b]:
-						if c == 'tax_rate':
-							tax_details[itemised_tax[a][b][c]] += itemised_tax[a][b]['tax_amount']
-
-	for t in tax_details:
-		tax_breakup.append({'rate': t, 'amount': tax_details[t]})
-
-	return tax_breakup
-
-def get_sales_summary(invoice_list):
-	net_total = sum(item['net_total'] for item in invoice_list)
-	grand_total = sum(item['grand_total'] for item in invoice_list)
-	total_qty = sum(item['pos_total_qty'] for item in invoice_list)
-
-	return {'net_total': net_total, 'grand_total': grand_total, 'total_qty': total_qty}
-
-def get_company_currency(doc):
-	currency = frappe.get_cached_value('Company',  doc.company,  "default_currency")
-	return frappe.get_doc('Currency', currency)
-
-def get_invoices(filters):
-	return frappe.db.sql("""select a.name, a.base_grand_total as grand_total,
-		a.base_net_total as net_total, a.pos_total_qty
-		from `tabSales Invoice` a
-		where a.docstatus = 1 and a.posting_date >= %(from_date)s
-		and a.posting_date <= %(to_date)s and a.company=%(company)s
-		and a.pos_profile = %(pos_profile)s and a.is_pos = %(is_pos)s
-		and a.owner = %(user)s""",
-		filters, as_dict=1)
diff --git a/erpnext/selling/doctype/pos_closing_voucher/test_pos_closing_voucher.py b/erpnext/selling/doctype/pos_closing_voucher/test_pos_closing_voucher.py
deleted file mode 100644
index 8899aaf..0000000
--- a/erpnext/selling/doctype/pos_closing_voucher/test_pos_closing_voucher.py
+++ /dev/null
@@ -1,83 +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
-from frappe.utils import nowdate
-from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
-from erpnext.accounts.doctype.pos_profile.test_pos_profile import make_pos_profile
-
-class TestPOSClosingVoucher(unittest.TestCase):
-	def test_pos_closing_voucher(self):
-		old_user = frappe.session.user
-		user = 'test@example.com'
-		test_user = frappe.get_doc('User', user)
-
-		roles = ("Accounts Manager", "Accounts User", "Sales Manager")
-		test_user.add_roles(*roles)
-		frappe.set_user(user)
-
-		pos_profile = make_pos_profile()
-		pos_profile.append('applicable_for_users', {
-			'default': 1,
-			'user': user
-		})
-
-		pos_profile.save()
-
-		si1 = create_sales_invoice(is_pos=1, rate=3500, do_not_submit=1)
-		si1.append('payments', {
-			'mode_of_payment': 'Cash', 'account': 'Cash - _TC', 'amount': 3500
-		})
-		si1.submit()
-
-		si2 = create_sales_invoice(is_pos=1, rate=3200, do_not_submit=1)
-		si2.append('payments', {
-			'mode_of_payment': 'Cash', 'account': 'Cash - _TC', 'amount': 3200
-		})
-		si2.submit()
-
-		pcv_doc = create_pos_closing_voucher(user=user,
-			pos_profile=pos_profile.name, collected_amount=6700)
-
-		pcv_doc.get_closing_voucher_details()
-
-		self.assertEqual(pcv_doc.total_quantity, 2)
-		self.assertEqual(pcv_doc.net_total, 6700)
-
-		payment = pcv_doc.payment_reconciliation[0]
-		self.assertEqual(payment.mode_of_payment, 'Cash')
-
-		si1.load_from_db()
-		si1.cancel()
-
-		si2.load_from_db()
-		si2.cancel()
-
-		test_user.load_from_db()
-		test_user.remove_roles(*roles)
-
-		frappe.set_user(old_user)
-		frappe.db.sql("delete from `tabPOS Profile`")
-
-def create_pos_closing_voucher(**args):
-	args = frappe._dict(args)
-
-	doc = frappe.get_doc({
-		'doctype': 'POS Closing Voucher',
-		'period_start_date': args.period_start_date or nowdate(),
-		'period_end_date': args.period_end_date or nowdate(),
-		'posting_date': args.posting_date or nowdate(),
-		'company': args.company or "_Test Company",
-		'pos_profile': args.pos_profile,
-		'user': args.user or "Administrator",
-	})
-
-	doc.get_closing_voucher_details()
-	if doc.get('payment_reconciliation'):
-		doc.payment_reconciliation[0].collected_amount = (args.collected_amount or
-			doc.payment_reconciliation[0].expected_amount)
-
-	doc.save()
-	return doc
\ No newline at end of file
diff --git a/erpnext/selling/doctype/pos_closing_voucher_details/__init__.py b/erpnext/selling/doctype/pos_closing_voucher_details/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/selling/doctype/pos_closing_voucher_details/__init__.py
+++ /dev/null
diff --git a/erpnext/selling/doctype/pos_closing_voucher_details/pos_closing_voucher_details.json b/erpnext/selling/doctype/pos_closing_voucher_details/pos_closing_voucher_details.json
deleted file mode 100644
index a526884..0000000
--- a/erpnext/selling/doctype/pos_closing_voucher_details/pos_closing_voucher_details.json
+++ /dev/null
@@ -1,172 +0,0 @@
-{
- "allow_copy": 0, 
- "allow_guest_to_view": 0, 
- "allow_import": 0, 
- "allow_rename": 0, 
- "beta": 0, 
- "creation": "2018-05-28 19:10:47.580174", 
- "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": "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": 1, 
-   "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": 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, 
-   "default": "0.0", 
-   "fieldname": "collected_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": "Collected 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
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "expected_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": "Expected 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, 
-   "fieldname": "difference", 
-   "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": "Difference", 
-   "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
-  }
- ], 
- "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-05-29 17:47:16.311557", 
- "modified_by": "Administrator", 
- "module": "Selling", 
- "name": "POS Closing Voucher Details", 
- "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
-}
\ No newline at end of file
diff --git a/erpnext/selling/doctype/pos_closing_voucher_details/pos_closing_voucher_details.py b/erpnext/selling/doctype/pos_closing_voucher_details/pos_closing_voucher_details.py
deleted file mode 100644
index 6bc323f..0000000
--- a/erpnext/selling/doctype/pos_closing_voucher_details/pos_closing_voucher_details.py
+++ /dev/null
@@ -1,9 +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
-from frappe.model.document import Document
-
-class POSClosingVoucherDetails(Document):
-	pass
diff --git a/erpnext/selling/doctype/pos_closing_voucher_invoices/__init__.py b/erpnext/selling/doctype/pos_closing_voucher_invoices/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/selling/doctype/pos_closing_voucher_invoices/__init__.py
+++ /dev/null
diff --git a/erpnext/selling/doctype/pos_closing_voucher_invoices/pos_closing_voucher_invoices.json b/erpnext/selling/doctype/pos_closing_voucher_invoices/pos_closing_voucher_invoices.json
deleted file mode 100644
index 7304550..0000000
--- a/erpnext/selling/doctype/pos_closing_voucher_invoices/pos_closing_voucher_invoices.json
+++ /dev/null
@@ -1,138 +0,0 @@
-{
- "allow_copy": 0, 
- "allow_guest_to_view": 0, 
- "allow_import": 0, 
- "allow_rename": 0, 
- "beta": 0, 
- "creation": "2018-05-29 14:50:08.687453", 
- "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": "invoice", 
-   "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": "Invoices", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Sales Invoice", 
-   "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, 
-   "fieldname": "qty_of_items", 
-   "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": "Quantity of Items", 
-   "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, 
-   "fieldname": "grand_total", 
-   "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": "Grand Total", 
-   "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
-  }
- ], 
- "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-05-29 17:46:46.539993", 
- "modified_by": "Administrator", 
- "module": "Selling", 
- "name": "POS Closing Voucher Invoices", 
- "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
-}
\ No newline at end of file
diff --git a/erpnext/selling/doctype/pos_closing_voucher_taxes/__init__.py b/erpnext/selling/doctype/pos_closing_voucher_taxes/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/selling/doctype/pos_closing_voucher_taxes/__init__.py
+++ /dev/null
diff --git a/erpnext/selling/doctype/pos_closing_voucher_taxes/pos_closing_voucher_taxes.json b/erpnext/selling/doctype/pos_closing_voucher_taxes/pos_closing_voucher_taxes.json
deleted file mode 100644
index 3089e06..0000000
--- a/erpnext/selling/doctype/pos_closing_voucher_taxes/pos_closing_voucher_taxes.json
+++ /dev/null
@@ -1,106 +0,0 @@
-{
- "allow_copy": 0, 
- "allow_guest_to_view": 0, 
- "allow_import": 0, 
- "allow_rename": 0, 
- "beta": 0, 
- "creation": "2018-05-30 09:11:22.535470", 
- "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": "rate", 
-   "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": "Rate", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "", 
-   "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, 
-   "fieldname": "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": "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
-  }
- ], 
- "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-05-30 09:11:22.535470", 
- "modified_by": "Administrator", 
- "module": "Selling", 
- "name": "POS Closing Voucher Taxes", 
- "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
-}
\ No newline at end of file
diff --git a/erpnext/selling/doctype/product_bundle/product_bundle.py b/erpnext/selling/doctype/product_bundle/product_bundle.py
index c8a7167..0c85a1b 100644
--- a/erpnext/selling/doctype/product_bundle/product_bundle.py
+++ b/erpnext/selling/doctype/product_bundle/product_bundle.py
@@ -22,12 +22,13 @@
 		"""Validates, main Item is not a stock item"""
 		if frappe.db.get_value("Item", self.new_item_code, "is_stock_item"):
 			frappe.throw(_("Parent Item {0} must not be a Stock Item").format(self.new_item_code))
-			
+
 	def validate_child_items(self):
 		for item in self.items:
 			if frappe.db.exists("Product Bundle", item.item_code):
-				frappe.throw(_("Child Item should not be a Product Bundle. Please remove item `{0}` and save").format(item.item_code))
-				
+				frappe.throw(_("Row #{0}: Child Item should not be a Product Bundle. Please remove Item {1} and Save").format(item.idx, frappe.bold(item.item_code)))
+
+@frappe.whitelist()
 def get_new_item_code(doctype, txt, searchfield, start, page_len, filters):
 	from erpnext.controllers.queries import get_match_cond
 
diff --git a/erpnext/selling/doctype/product_bundle/test_product_bundle.py b/erpnext/selling/doctype/product_bundle/test_product_bundle.py
index 85a2b20..7d1d372 100644
--- a/erpnext/selling/doctype/product_bundle/test_product_bundle.py
+++ b/erpnext/selling/doctype/product_bundle/test_product_bundle.py
@@ -7,7 +7,7 @@
 import frappe
 test_records = frappe.get_test_records('Product Bundle')
 
-def make_product_bundle(parent, items):
+def make_product_bundle(parent, items, qty=None):
 	if frappe.db.exists("Product Bundle", parent):
 		return frappe.get_doc("Product Bundle", parent)
 
@@ -17,7 +17,7 @@
 	})
 
 	for item in items:
-		product_bundle.append("items", {"item_code": item, "qty": 1})
+		product_bundle.append("items", {"item_code": item, "qty": qty or 1})
 
 	product_bundle.insert()
 
diff --git a/erpnext/selling/doctype/quotation/quotation.json b/erpnext/selling/doctype/quotation/quotation.json
index 8e21927..6d34c2a 100644
--- a/erpnext/selling/doctype/quotation/quotation.json
+++ b/erpnext/selling/doctype/quotation/quotation.json
@@ -654,6 +654,7 @@
    "fieldname": "base_in_words",
    "fieldtype": "Data",
    "label": "In Words (Company Currency)",
+   "length": 240,
    "oldfieldname": "in_words",
    "oldfieldtype": "Data",
    "print_hide": 1,
@@ -713,6 +714,7 @@
    "fieldname": "in_words",
    "fieldtype": "Data",
    "label": "In Words",
+   "length": 240,
    "oldfieldname": "in_words_export",
    "oldfieldtype": "Data",
    "print_hide": 1,
@@ -930,7 +932,7 @@
  "is_submittable": 1,
  "links": [],
  "max_attachments": 1,
- "modified": "2019-12-30 19:14:56.630270",
+ "modified": "2020-07-18 04:59:09.960118",
  "modified_by": "Administrator",
  "module": "Selling",
  "name": "Quotation",
diff --git a/erpnext/selling/doctype/quotation/quotation_list.js b/erpnext/selling/doctype/quotation/quotation_list.js
index 802c0ba..f425acf 100644
--- a/erpnext/selling/doctype/quotation/quotation_list.js
+++ b/erpnext/selling/doctype/quotation/quotation_list.js
@@ -3,13 +3,15 @@
 		"company", "currency", 'valid_till'],
 
 	onload: function(listview) {
-		listview.page.fields_dict.quotation_to.get_query = function() {
-			return {
-				"filters": {
-					"name": ["in", ["Customer", "Lead"]],
-				}
+		if (listview.page.fields_dict.quotation_to) {
+			listview.page.fields_dict.quotation_to.get_query = function() {
+				return {
+					"filters": {
+						"name": ["in", ["Customer", "Lead"]],
+					}
+				};
 			};
-		};
+		}
 	},
 
 	get_indicator: function(doc) {
diff --git a/erpnext/selling/doctype/quotation/test_quotation.py b/erpnext/selling/doctype/quotation/test_quotation.py
index ee6b429..b4c3d79 100644
--- a/erpnext/selling/doctype/quotation/test_quotation.py
+++ b/erpnext/selling/doctype/quotation/test_quotation.py
@@ -280,5 +280,3 @@
 			qo.submit()
 
 	return qo
-
-
diff --git a/erpnext/selling/doctype/sales_order/sales_order.json b/erpnext/selling/doctype/sales_order/sales_order.json
index b57c4f3..8fa56ac 100644
--- a/erpnext/selling/doctype/sales_order/sales_order.json
+++ b/erpnext/selling/doctype/sales_order/sales_order.json
@@ -1,6 +1,7 @@
 {
  "actions": [],
  "allow_import": 1,
+ "allow_workflow": 1,
  "autoname": "naming_series:",
  "creation": "2013-06-18 12:39:59",
  "doctype": "DocType",
@@ -143,11 +144,15 @@
   {
    "fieldname": "customer_section",
    "fieldtype": "Section Break",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "options": "fa fa-user"
   },
   {
    "fieldname": "column_break0",
    "fieldtype": "Column Break",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "oldfieldtype": "Column Break",
    "width": "50%"
   },
@@ -157,6 +162,8 @@
    "fieldname": "title",
    "fieldtype": "Data",
    "hidden": 1,
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Title",
    "no_copy": 1,
    "print_hide": 1
@@ -164,6 +171,8 @@
   {
    "fieldname": "naming_series",
    "fieldtype": "Select",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Series",
    "no_copy": 1,
    "oldfieldname": "naming_series",
@@ -177,6 +186,8 @@
    "bold": 1,
    "fieldname": "customer",
    "fieldtype": "Link",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "in_global_search": 1,
    "in_standard_filter": 1,
    "label": "Customer",
@@ -192,6 +203,8 @@
    "fetch_from": "customer.customer_name",
    "fieldname": "customer_name",
    "fieldtype": "Data",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "in_global_search": 1,
    "label": "Customer Name",
    "read_only": 1
@@ -200,6 +213,8 @@
    "default": "Sales",
    "fieldname": "order_type",
    "fieldtype": "Select",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Order Type",
    "oldfieldname": "order_type",
    "oldfieldtype": "Select",
@@ -210,6 +225,8 @@
   {
    "fieldname": "column_break1",
    "fieldtype": "Column Break",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "oldfieldtype": "Column Break",
    "width": "50%"
   },
@@ -217,6 +234,8 @@
    "fieldname": "amended_from",
    "fieldtype": "Link",
    "hidden": 1,
+   "hide_days": 1,
+   "hide_seconds": 1,
    "ignore_user_permissions": 1,
    "label": "Amended From",
    "no_copy": 1,
@@ -230,6 +249,8 @@
   {
    "fieldname": "company",
    "fieldtype": "Link",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "in_standard_filter": 1,
    "label": "Company",
    "oldfieldname": "company",
@@ -244,6 +265,8 @@
    "default": "Today",
    "fieldname": "transaction_date",
    "fieldtype": "Date",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "in_standard_filter": 1,
    "label": "Date",
    "no_copy": 1,
@@ -258,6 +281,8 @@
    "depends_on": "eval:!doc.skip_delivery_note",
    "fieldname": "delivery_date",
    "fieldtype": "Date",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "in_list_view": 1,
    "label": "Delivery Date",
    "no_copy": 1
@@ -266,6 +291,8 @@
    "allow_on_submit": 1,
    "fieldname": "po_no",
    "fieldtype": "Data",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Customer's Purchase Order",
    "oldfieldname": "po_no",
    "oldfieldtype": "Data",
@@ -276,6 +303,8 @@
    "depends_on": "eval:doc.po_no",
    "fieldname": "po_date",
    "fieldtype": "Date",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Customer's Purchase Order Date",
    "oldfieldname": "po_date",
    "oldfieldtype": "Date",
@@ -285,6 +314,8 @@
    "fetch_from": "customer.tax_id",
    "fieldname": "tax_id",
    "fieldtype": "Data",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Tax Id",
    "read_only": 1,
    "width": "100px"
@@ -294,6 +325,8 @@
    "depends_on": "customer",
    "fieldname": "contact_info",
    "fieldtype": "Section Break",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Address and Contact",
    "options": "fa fa-bullhorn"
   },
@@ -301,6 +334,8 @@
    "allow_on_submit": 1,
    "fieldname": "customer_address",
    "fieldtype": "Link",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Customer Address",
    "options": "Address",
    "print_hide": 1
@@ -309,12 +344,16 @@
    "allow_on_submit": 1,
    "fieldname": "address_display",
    "fieldtype": "Small Text",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Address",
    "read_only": 1
   },
   {
    "fieldname": "contact_person",
    "fieldtype": "Link",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Contact Person",
    "options": "Contact",
    "print_hide": 1
@@ -322,6 +361,8 @@
   {
    "fieldname": "contact_display",
    "fieldtype": "Small Text",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "in_global_search": 1,
    "label": "Contact",
    "read_only": 1
@@ -329,6 +370,8 @@
   {
    "fieldname": "contact_mobile",
    "fieldtype": "Small Text",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Mobile No",
    "read_only": 1
   },
@@ -336,6 +379,8 @@
    "fieldname": "contact_email",
    "fieldtype": "Data",
    "hidden": 1,
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Contact Email",
    "options": "Email",
    "print_hide": 1,
@@ -344,24 +389,32 @@
   {
    "fieldname": "company_address_display",
    "fieldtype": "Small Text",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Company Address",
    "read_only": 1
   },
   {
    "fieldname": "company_address",
    "fieldtype": "Link",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Company Address Name",
    "options": "Address"
   },
   {
    "fieldname": "col_break46",
    "fieldtype": "Column Break",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "width": "50%"
   },
   {
    "allow_on_submit": 1,
    "fieldname": "shipping_address_name",
    "fieldtype": "Link",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Shipping Address Name",
    "options": "Address",
    "print_hide": 1
@@ -370,6 +423,8 @@
    "allow_on_submit": 1,
    "fieldname": "shipping_address",
    "fieldtype": "Small Text",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Shipping Address",
    "print_hide": 1,
    "read_only": 1
@@ -378,6 +433,8 @@
    "fieldname": "customer_group",
    "fieldtype": "Link",
    "hidden": 1,
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Customer Group",
    "options": "Customer Group",
    "print_hide": 1
@@ -385,6 +442,8 @@
   {
    "fieldname": "territory",
    "fieldtype": "Link",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Territory",
    "options": "Territory",
    "print_hide": 1
@@ -393,6 +452,8 @@
    "collapsible": 1,
    "fieldname": "currency_and_price_list",
    "fieldtype": "Section Break",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Currency and Price List",
    "options": "fa fa-tag",
    "print_hide": 1
@@ -400,6 +461,8 @@
   {
    "fieldname": "currency",
    "fieldtype": "Link",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Currency",
    "oldfieldname": "currency",
    "oldfieldtype": "Select",
@@ -412,6 +475,8 @@
    "description": "Rate at which customer's currency is converted to company's base currency",
    "fieldname": "conversion_rate",
    "fieldtype": "Float",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Exchange Rate",
    "oldfieldname": "conversion_rate",
    "oldfieldtype": "Currency",
@@ -423,11 +488,15 @@
   {
    "fieldname": "column_break2",
    "fieldtype": "Column Break",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "width": "50%"
   },
   {
    "fieldname": "selling_price_list",
    "fieldtype": "Link",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Price List",
    "oldfieldname": "price_list_name",
    "oldfieldtype": "Select",
@@ -439,6 +508,8 @@
   {
    "fieldname": "price_list_currency",
    "fieldtype": "Link",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Price List Currency",
    "options": "Currency",
    "print_hide": 1,
@@ -449,6 +520,8 @@
    "description": "Rate at which Price list currency is converted to company's base currency",
    "fieldname": "plc_conversion_rate",
    "fieldtype": "Float",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Price List Exchange Rate",
    "precision": "9",
    "print_hide": 1,
@@ -458,6 +531,8 @@
    "default": "0",
    "fieldname": "ignore_pricing_rule",
    "fieldtype": "Check",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Ignore Pricing Rule",
    "no_copy": 1,
    "permlevel": 1,
@@ -465,11 +540,15 @@
   },
   {
    "fieldname": "sec_warehouse",
-   "fieldtype": "Section Break"
+   "fieldtype": "Section Break",
+   "hide_days": 1,
+   "hide_seconds": 1
   },
   {
    "fieldname": "set_warehouse",
    "fieldtype": "Link",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Set Source Warehouse",
    "options": "Warehouse",
    "print_hide": 1
@@ -477,18 +556,24 @@
   {
    "fieldname": "items_section",
    "fieldtype": "Section Break",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "oldfieldtype": "Section Break",
    "options": "fa fa-shopping-cart"
   },
   {
    "fieldname": "scan_barcode",
    "fieldtype": "Data",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Scan Barcode"
   },
   {
    "allow_bulk_edit": 1,
    "fieldname": "items",
    "fieldtype": "Table",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Items",
    "oldfieldname": "sales_order_details",
    "oldfieldtype": "Table",
@@ -498,32 +583,44 @@
   {
    "fieldname": "pricing_rule_details",
    "fieldtype": "Section Break",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Pricing Rules"
   },
   {
    "fieldname": "pricing_rules",
    "fieldtype": "Table",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Pricing Rule Detail",
    "options": "Pricing Rule Detail",
    "read_only": 1
   },
   {
    "fieldname": "section_break_31",
-   "fieldtype": "Section Break"
+   "fieldtype": "Section Break",
+   "hide_days": 1,
+   "hide_seconds": 1
   },
   {
    "fieldname": "column_break_33a",
-   "fieldtype": "Column Break"
+   "fieldtype": "Column Break",
+   "hide_days": 1,
+   "hide_seconds": 1
   },
   {
    "fieldname": "total_qty",
    "fieldtype": "Float",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Total Quantity",
    "read_only": 1
   },
   {
    "fieldname": "base_total",
    "fieldtype": "Currency",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Total (Company Currency)",
    "options": "Company:company:default_currency",
    "print_hide": 1,
@@ -532,6 +629,8 @@
   {
    "fieldname": "base_net_total",
    "fieldtype": "Currency",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Net Total (Company Currency)",
    "oldfieldname": "net_total",
    "oldfieldtype": "Currency",
@@ -542,11 +641,15 @@
   },
   {
    "fieldname": "column_break_33",
-   "fieldtype": "Column Break"
+   "fieldtype": "Column Break",
+   "hide_days": 1,
+   "hide_seconds": 1
   },
   {
    "fieldname": "total",
    "fieldtype": "Currency",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Total",
    "options": "currency",
    "read_only": 1
@@ -554,6 +657,8 @@
   {
    "fieldname": "net_total",
    "fieldtype": "Currency",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Net Total",
    "options": "currency",
    "print_hide": 1,
@@ -562,6 +667,8 @@
   {
    "fieldname": "total_net_weight",
    "fieldtype": "Float",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Total Net Weight",
    "print_hide": 1,
    "read_only": 1
@@ -569,6 +676,8 @@
   {
    "fieldname": "taxes_section",
    "fieldtype": "Section Break",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Taxes and Charges",
    "oldfieldtype": "Section Break",
    "options": "fa fa-money"
@@ -576,17 +685,23 @@
   {
    "fieldname": "tax_category",
    "fieldtype": "Link",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Tax Category",
    "options": "Tax Category",
    "print_hide": 1
   },
   {
    "fieldname": "column_break_38",
-   "fieldtype": "Column Break"
+   "fieldtype": "Column Break",
+   "hide_days": 1,
+   "hide_seconds": 1
   },
   {
    "fieldname": "shipping_rule",
    "fieldtype": "Link",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Shipping Rule",
    "oldfieldtype": "Button",
    "options": "Shipping Rule",
@@ -594,11 +709,15 @@
   },
   {
    "fieldname": "section_break_40",
-   "fieldtype": "Section Break"
+   "fieldtype": "Section Break",
+   "hide_days": 1,
+   "hide_seconds": 1
   },
   {
    "fieldname": "taxes_and_charges",
    "fieldtype": "Link",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Sales Taxes and Charges Template",
    "oldfieldname": "charge",
    "oldfieldtype": "Link",
@@ -608,6 +727,8 @@
   {
    "fieldname": "taxes",
    "fieldtype": "Table",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Sales Taxes and Charges",
    "oldfieldname": "other_charges",
    "oldfieldtype": "Table",
@@ -617,11 +738,15 @@
    "collapsible": 1,
    "fieldname": "sec_tax_breakup",
    "fieldtype": "Section Break",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Tax Breakup"
   },
   {
    "fieldname": "other_charges_calculation",
    "fieldtype": "Long Text",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Taxes and Charges Calculation",
    "no_copy": 1,
    "oldfieldtype": "HTML",
@@ -630,11 +755,15 @@
   },
   {
    "fieldname": "section_break_43",
-   "fieldtype": "Section Break"
+   "fieldtype": "Section Break",
+   "hide_days": 1,
+   "hide_seconds": 1
   },
   {
    "fieldname": "base_total_taxes_and_charges",
    "fieldtype": "Currency",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Total Taxes and Charges (Company Currency)",
    "oldfieldname": "other_charges_total",
    "oldfieldtype": "Currency",
@@ -645,11 +774,15 @@
   },
   {
    "fieldname": "column_break_46",
-   "fieldtype": "Column Break"
+   "fieldtype": "Column Break",
+   "hide_days": 1,
+   "hide_seconds": 1
   },
   {
    "fieldname": "total_taxes_and_charges",
    "fieldtype": "Currency",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Total Taxes and Charges",
    "options": "currency",
    "print_hide": 1,
@@ -659,6 +792,8 @@
    "fieldname": "loyalty_points_redemption",
    "fieldtype": "Section Break",
    "hidden": 1,
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Loyalty Points Redemption",
    "print_hide": 1
   },
@@ -666,6 +801,8 @@
    "fieldname": "loyalty_points",
    "fieldtype": "Int",
    "hidden": 1,
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Loyalty Points",
    "read_only": 1
   },
@@ -673,6 +810,8 @@
    "fieldname": "loyalty_amount",
    "fieldtype": "Currency",
    "hidden": 1,
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Loyalty Amount",
    "print_hide": 1,
    "read_only": 1
@@ -682,11 +821,15 @@
    "collapsible_depends_on": "discount_amount",
    "fieldname": "section_break_48",
    "fieldtype": "Section Break",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Additional Discount and Coupon Code"
   },
   {
    "fieldname": "coupon_code",
    "fieldtype": "Link",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Coupon Code",
    "options": "Coupon Code"
   },
@@ -694,6 +837,8 @@
    "default": "Grand Total",
    "fieldname": "apply_discount_on",
    "fieldtype": "Select",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Apply Additional Discount On",
    "options": "\nGrand Total\nNet Total",
    "print_hide": 1
@@ -701,6 +846,8 @@
   {
    "fieldname": "base_discount_amount",
    "fieldtype": "Currency",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Additional Discount Amount (Company Currency)",
    "options": "Company:company:default_currency",
    "print_hide": 1,
@@ -708,17 +855,23 @@
   },
   {
    "fieldname": "column_break_50",
-   "fieldtype": "Column Break"
+   "fieldtype": "Column Break",
+   "hide_days": 1,
+   "hide_seconds": 1
   },
   {
    "fieldname": "additional_discount_percentage",
    "fieldtype": "Float",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Additional Discount Percentage",
    "print_hide": 1
   },
   {
    "fieldname": "discount_amount",
    "fieldtype": "Currency",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Additional Discount Amount",
    "options": "currency",
    "print_hide": 1
@@ -726,6 +879,8 @@
   {
    "fieldname": "totals",
    "fieldtype": "Section Break",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "oldfieldtype": "Section Break",
    "options": "fa fa-money",
    "print_hide": 1
@@ -733,6 +888,8 @@
   {
    "fieldname": "base_grand_total",
    "fieldtype": "Currency",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Grand Total (Company Currency)",
    "oldfieldname": "grand_total",
    "oldfieldtype": "Currency",
@@ -744,6 +901,8 @@
   {
    "fieldname": "base_rounding_adjustment",
    "fieldtype": "Currency",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Rounding Adjustment (Company Currency)",
    "no_copy": 1,
    "options": "Company:company:default_currency",
@@ -753,6 +912,8 @@
   {
    "fieldname": "base_rounded_total",
    "fieldtype": "Currency",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Rounded Total (Company Currency)",
    "oldfieldname": "rounded_total",
    "oldfieldtype": "Currency",
@@ -765,7 +926,10 @@
    "description": "In Words will be visible once you save the Sales Order.",
    "fieldname": "base_in_words",
    "fieldtype": "Data",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "In Words (Company Currency)",
+   "length": 240,
    "oldfieldname": "in_words",
    "oldfieldtype": "Data",
    "print_hide": 1,
@@ -775,6 +939,8 @@
   {
    "fieldname": "column_break3",
    "fieldtype": "Column Break",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "oldfieldtype": "Column Break",
    "print_hide": 1,
    "width": "50%"
@@ -782,6 +948,8 @@
   {
    "fieldname": "grand_total",
    "fieldtype": "Currency",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "in_list_view": 1,
    "label": "Grand Total",
    "oldfieldname": "grand_total_export",
@@ -793,6 +961,8 @@
   {
    "fieldname": "rounding_adjustment",
    "fieldtype": "Currency",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Rounding Adjustment",
    "no_copy": 1,
    "options": "currency",
@@ -803,6 +973,8 @@
    "bold": 1,
    "fieldname": "rounded_total",
    "fieldtype": "Currency",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Rounded Total",
    "oldfieldname": "rounded_total_export",
    "oldfieldtype": "Currency",
@@ -813,7 +985,10 @@
   {
    "fieldname": "in_words",
    "fieldtype": "Data",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "In Words",
+   "length": 240,
    "oldfieldname": "in_words_export",
    "oldfieldtype": "Data",
    "print_hide": 1,
@@ -823,6 +998,8 @@
   {
    "fieldname": "advance_paid",
    "fieldtype": "Currency",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Advance Paid",
    "no_copy": 1,
    "options": "party_account_currency",
@@ -834,6 +1011,8 @@
    "collapsible_depends_on": "packed_items",
    "fieldname": "packing_list",
    "fieldtype": "Section Break",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Packing List",
    "oldfieldtype": "Section Break",
    "options": "fa fa-suitcase",
@@ -842,6 +1021,8 @@
   {
    "fieldname": "packed_items",
    "fieldtype": "Table",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Packed Items",
    "options": "Packed Item",
    "print_hide": 1,
@@ -850,11 +1031,15 @@
   {
    "fieldname": "payment_schedule_section",
    "fieldtype": "Section Break",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Payment Terms"
   },
   {
    "fieldname": "payment_terms_template",
    "fieldtype": "Link",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Payment Terms Template",
    "options": "Payment Terms Template",
    "print_hide": 1
@@ -862,6 +1047,8 @@
   {
    "fieldname": "payment_schedule",
    "fieldtype": "Table",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Payment Schedule",
    "no_copy": 1,
    "options": "Payment Schedule",
@@ -872,6 +1059,8 @@
    "collapsible_depends_on": "terms",
    "fieldname": "terms_section_break",
    "fieldtype": "Section Break",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Terms and Conditions",
    "oldfieldtype": "Section Break",
    "options": "fa fa-legal"
@@ -879,6 +1068,8 @@
   {
    "fieldname": "tc_name",
    "fieldtype": "Link",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Terms",
    "oldfieldname": "tc_name",
    "oldfieldtype": "Link",
@@ -888,6 +1079,8 @@
   {
    "fieldname": "terms",
    "fieldtype": "Text Editor",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Terms and Conditions Details",
    "oldfieldname": "terms",
    "oldfieldtype": "Text Editor"
@@ -897,6 +1090,8 @@
    "collapsible_depends_on": "project",
    "fieldname": "more_info",
    "fieldtype": "Section Break",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "More Information",
    "oldfieldtype": "Section Break",
    "options": "fa fa-file-text",
@@ -905,6 +1100,8 @@
   {
    "fieldname": "inter_company_order_reference",
    "fieldtype": "Link",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Inter Company Order Reference",
    "options": "Purchase Order"
   },
@@ -912,6 +1109,8 @@
    "description": "Track this Sales Order against any Project",
    "fieldname": "project",
    "fieldtype": "Link",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Project",
    "oldfieldname": "project",
    "oldfieldtype": "Link",
@@ -921,6 +1120,8 @@
    "fieldname": "party_account_currency",
    "fieldtype": "Link",
    "hidden": 1,
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Party Account Currency",
    "no_copy": 1,
    "options": "Currency",
@@ -929,11 +1130,15 @@
   },
   {
    "fieldname": "column_break_77",
-   "fieldtype": "Column Break"
+   "fieldtype": "Column Break",
+   "hide_days": 1,
+   "hide_seconds": 1
   },
   {
    "fieldname": "source",
    "fieldtype": "Link",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Source",
    "oldfieldname": "source",
    "oldfieldtype": "Select",
@@ -943,6 +1148,8 @@
   {
    "fieldname": "campaign",
    "fieldtype": "Link",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Campaign",
    "oldfieldname": "campaign",
    "oldfieldtype": "Link",
@@ -953,11 +1160,15 @@
    "collapsible": 1,
    "fieldname": "printing_details",
    "fieldtype": "Section Break",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Print Settings"
   },
   {
    "fieldname": "language",
    "fieldtype": "Data",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Print Language",
    "print_hide": 1,
    "read_only": 1
@@ -966,6 +1177,8 @@
    "allow_on_submit": 1,
    "fieldname": "letter_head",
    "fieldtype": "Link",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Letter Head",
    "oldfieldname": "letter_head",
    "oldfieldtype": "Select",
@@ -975,6 +1188,8 @@
   {
    "fieldname": "column_break4",
    "fieldtype": "Column Break",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "oldfieldtype": "Column Break",
    "print_hide": 1,
    "width": "50%"
@@ -983,6 +1198,8 @@
    "allow_on_submit": 1,
    "fieldname": "select_print_heading",
    "fieldtype": "Link",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Print Heading",
    "no_copy": 1,
    "oldfieldname": "select_print_heading",
@@ -996,6 +1213,8 @@
    "default": "0",
    "fieldname": "group_same_items",
    "fieldtype": "Check",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Group same items",
    "print_hide": 1
   },
@@ -1003,6 +1222,8 @@
    "collapsible": 1,
    "fieldname": "section_break_78",
    "fieldtype": "Section Break",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Billing and Delivery Status",
    "oldfieldtype": "Column Break",
    "print_hide": 1,
@@ -1012,6 +1233,8 @@
    "default": "Draft",
    "fieldname": "status",
    "fieldtype": "Select",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "in_list_view": 1,
    "label": "Status",
    "no_copy": 1,
@@ -1028,6 +1251,8 @@
    "fieldname": "delivery_status",
    "fieldtype": "Select",
    "hidden": 1,
+   "hide_days": 1,
+   "hide_seconds": 1,
    "in_standard_filter": 1,
    "label": "Delivery Status",
    "no_copy": 1,
@@ -1039,6 +1264,8 @@
    "description": "% of materials delivered against this Sales Order",
    "fieldname": "per_delivered",
    "fieldtype": "Percent",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "in_list_view": 1,
    "label": "%  Delivered",
    "no_copy": 1,
@@ -1050,13 +1277,17 @@
   },
   {
    "fieldname": "column_break_81",
-   "fieldtype": "Column Break"
+   "fieldtype": "Column Break",
+   "hide_days": 1,
+   "hide_seconds": 1
   },
   {
    "depends_on": "eval:!doc.__islocal",
    "description": "% of materials billed against this Sales Order",
    "fieldname": "per_billed",
    "fieldtype": "Percent",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "in_list_view": 1,
    "label": "% Amount Billed",
    "no_copy": 1,
@@ -1070,6 +1301,8 @@
    "fieldname": "billing_status",
    "fieldtype": "Select",
    "hidden": 1,
+   "hide_days": 1,
+   "hide_seconds": 1,
    "in_standard_filter": 1,
    "label": "Billing Status",
    "no_copy": 1,
@@ -1081,6 +1314,8 @@
    "collapsible_depends_on": "commission_rate",
    "fieldname": "sales_team_section_break",
    "fieldtype": "Section Break",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Commission",
    "oldfieldtype": "Section Break",
    "options": "fa fa-group",
@@ -1089,6 +1324,8 @@
   {
    "fieldname": "sales_partner",
    "fieldtype": "Link",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Sales Partner",
    "oldfieldname": "sales_partner",
    "oldfieldtype": "Link",
@@ -1099,12 +1336,16 @@
   {
    "fieldname": "column_break7",
    "fieldtype": "Column Break",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "print_hide": 1,
    "width": "50%"
   },
   {
    "fieldname": "commission_rate",
    "fieldtype": "Float",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Commission Rate",
    "oldfieldname": "commission_rate",
    "oldfieldtype": "Currency",
@@ -1114,6 +1355,8 @@
   {
    "fieldname": "total_commission",
    "fieldtype": "Currency",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Total Commission",
    "oldfieldname": "total_commission",
    "oldfieldtype": "Currency",
@@ -1125,6 +1368,8 @@
    "collapsible_depends_on": "sales_team",
    "fieldname": "section_break1",
    "fieldtype": "Section Break",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Sales Team",
    "print_hide": 1
   },
@@ -1132,6 +1377,8 @@
    "allow_on_submit": 1,
    "fieldname": "sales_team",
    "fieldtype": "Table",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Sales Team",
    "oldfieldname": "sales_team",
    "oldfieldtype": "Table",
@@ -1140,8 +1387,11 @@
   },
   {
    "allow_on_submit": 1,
+   "collapsible": 1,
    "fieldname": "subscription_section",
    "fieldtype": "Section Break",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Auto Repeat Section",
    "no_copy": 1,
    "print_hide": 1,
@@ -1151,6 +1401,8 @@
    "allow_on_submit": 1,
    "fieldname": "from_date",
    "fieldtype": "Date",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "From Date",
    "no_copy": 1
   },
@@ -1158,16 +1410,22 @@
    "allow_on_submit": 1,
    "fieldname": "to_date",
    "fieldtype": "Date",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "To Date",
    "no_copy": 1
   },
   {
    "fieldname": "column_break_108",
-   "fieldtype": "Column Break"
+   "fieldtype": "Column Break",
+   "hide_days": 1,
+   "hide_seconds": 1
   },
   {
    "fieldname": "auto_repeat",
    "fieldtype": "Link",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Auto Repeat",
    "options": "Auto Repeat"
   },
@@ -1176,11 +1434,15 @@
    "depends_on": "eval: doc.auto_repeat",
    "fieldname": "update_auto_repeat_reference",
    "fieldtype": "Button",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Update Auto Repeat Reference"
   },
   {
    "fieldname": "contact_phone",
    "fieldtype": "Data",
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Phone",
    "read_only": 1
   },
@@ -1189,6 +1451,8 @@
    "fieldname": "skip_delivery_note",
    "fieldtype": "Check",
    "hidden": 1,
+   "hide_days": 1,
+   "hide_seconds": 1,
    "label": "Skip Delivery Note",
    "print_hide": 1
   }
@@ -1197,7 +1461,7 @@
  "idx": 105,
  "is_submittable": 1,
  "links": [],
- "modified": "2020-05-19 21:39:19.486684",
+ "modified": "2020-07-18 05:13:06.680696",
  "modified_by": "Administrator",
  "module": "Selling",
  "name": "Sales Order",
diff --git a/erpnext/selling/doctype/sales_order/test_records.json b/erpnext/selling/doctype/sales_order/test_records.json
index 6cbd6c2..8a090e6 100644
--- a/erpnext/selling/doctype/sales_order/test_records.json
+++ b/erpnext/selling/doctype/sales_order/test_records.json
@@ -1,39 +1,39 @@
 [
  {
   "advance_paid": 0.0,
-  "company": "_Test Company", 
-  "conversion_rate": 1.0, 
-  "currency": "INR", 
-  "customer": "_Test Customer", 
-  "customer_group": "_Test Customer Group", 
-  "customer_name": "_Test Customer", 
-  "doctype": "Sales Order", 
-  "base_grand_total": 1000.0, 
-  "grand_total": 1000.0, 
-  "naming_series": "_T-Sales Order-", 
-  "order_type": "Sales", 
-  "plc_conversion_rate": 1.0, 
-  "price_list_currency": "INR", 
+  "company": "_Test Company",
+  "conversion_rate": 1.0,
+  "currency": "INR",
+  "customer": "_Test Customer",
+  "customer_group": "_Test Customer Group",
+  "customer_name": "_Test Customer",
+  "doctype": "Sales Order",
+  "base_grand_total": 1000.0,
+  "grand_total": 1000.0,
+  "naming_series": "_T-Sales Order-",
+  "order_type": "Sales",
+  "plc_conversion_rate": 1.0,
+  "price_list_currency": "INR",
   "items": [
    {
-    "base_amount": 1000.0, 
-    "base_rate": 100.0, 
-    "description": "CPU", 
-    "doctype": "Sales Order Item", 
-    "item_code": "_Test Item Home Desktop 100", 
-    "item_name": "CPU", 
-    "delivery_date": "2013-02-23", 
-    "parentfield": "items", 
-    "qty": 10.0, 
-    "rate": 100.0, 
+    "base_amount": 1000.0,
+    "base_rate": 100.0,
+    "description": "CPU",
+    "doctype": "Sales Order Item",
+    "item_code": "_Test Item",
+    "item_name": "_Test Item 1",
+    "delivery_date": "2013-02-23",
+    "parentfield": "items",
+    "qty": 10.0,
+    "rate": 100.0,
     "warehouse": "_Test Warehouse - _TC",
     "stock_uom": "_Test UOM",
 	"conversion_factor": 1.0,
 	"uom": "_Test UOM"
    }
-  ], 
-  "selling_price_list": "_Test Price List", 
-  "territory": "_Test Territory", 
+  ],
+  "selling_price_list": "_Test Price List",
+  "territory": "_Test Territory",
   "transaction_date": "2013-02-21"
  }
 ]
\ No newline at end of file
diff --git a/erpnext/selling/doctype/sales_order/test_sales_order.py b/erpnext/selling/doctype/sales_order/test_sales_order.py
index 74e742f..accaa9c 100644
--- a/erpnext/selling/doctype/sales_order/test_sales_order.py
+++ b/erpnext/selling/doctype/sales_order/test_sales_order.py
@@ -2,6 +2,7 @@
 # License: GNU General Public License v3. See license.txt
 from __future__ import unicode_literals
 import frappe
+import json
 from frappe.utils import flt, add_days, nowdate
 import frappe.permissions
 import unittest
@@ -10,9 +11,10 @@
 from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry
 from erpnext.selling.doctype.sales_order.sales_order import make_work_orders
 from erpnext.controllers.accounts_controller import update_child_qty_rate
-import json
 from erpnext.selling.doctype.sales_order.sales_order import make_raw_material_request
 from erpnext.manufacturing.doctype.blanket_order.test_blanket_order import make_blanket_order
+from erpnext.selling.doctype.product_bundle.test_product_bundle import make_product_bundle
+from erpnext.stock.doctype.item.test_item import make_item
 
 class TestSalesOrder(unittest.TestCase):
 	def tearDown(self):
@@ -417,6 +419,26 @@
 		self.assertRaises(frappe.ValidationError, update_child_qty_rate,'Sales Order', trans_item, so.name)
 		frappe.set_user("Administrator")
 
+	def test_update_child_qty_rate_product_bundle(self):
+		# test Update Items with product bundle
+		if not frappe.db.exists("Item", "_Product Bundle Item"):
+			bundle_item = make_item("_Product Bundle Item", {"is_stock_item": 0})
+			bundle_item.append("item_defaults", {
+					"company": "_Test Company",
+					"default_warehouse": "_Test Warehouse - _TC"})
+			bundle_item.save(ignore_permissions=True)
+
+		make_item("_Packed Item", {"is_stock_item": 1})
+		make_product_bundle("_Product Bundle Item", ["_Packed Item"], 2)
+
+		so = make_sales_order(item_code = "_Test Item", warehouse=None)
+
+		added_item = json.dumps([{"item_code" : "_Product Bundle Item", "rate" : 200, 'qty' : 2}])
+		update_child_qty_rate('Sales Order', added_item, so.name)
+
+		so.reload()
+		self.assertEqual(so.packed_items[0].qty, 4)
+
 	def test_warehouse_user(self):
 		frappe.permissions.add_user_permission("Warehouse", "_Test Warehouse 1 - _TC", "test@example.com")
 		frappe.permissions.add_user_permission("Warehouse", "_Test Warehouse 2 - _TC1", "test2@example.com")
@@ -457,8 +479,6 @@
 		self.assertRaises(frappe.CancelledLinkError, dn.submit)
 
 	def test_service_type_product_bundle(self):
-		from erpnext.selling.doctype.product_bundle.test_product_bundle import make_product_bundle
-		from erpnext.stock.doctype.item.test_item import make_item
 		make_item("_Test Service Product Bundle", {"is_stock_item": 0})
 		make_item("_Test Service Product Bundle Item 1", {"is_stock_item": 0})
 		make_item("_Test Service Product Bundle Item 2", {"is_stock_item": 0})
@@ -472,8 +492,6 @@
 		self.assertTrue("_Test Service Product Bundle Item 2" in [d.item_code for d in so.packed_items])
 
 	def test_mix_type_product_bundle(self):
-		from erpnext.selling.doctype.product_bundle.test_product_bundle import make_product_bundle
-		from erpnext.stock.doctype.item.test_item import make_item
 		make_item("_Test Mix Product Bundle", {"is_stock_item": 0})
 		make_item("_Test Mix Product Bundle Item 1", {"is_stock_item": 1})
 		make_item("_Test Mix Product Bundle Item 2", {"is_stock_item": 0})
@@ -484,7 +502,6 @@
 		self.assertRaises(WarehouseRequired, make_sales_order, item_code = "_Test Mix Product Bundle", warehouse="")
 
 	def test_auto_insert_price(self):
-		from erpnext.stock.doctype.item.test_item import make_item
 		make_item("_Test Item for Auto Price List", {"is_stock_item": 0})
 		frappe.db.set_value("Stock Settings", None, "auto_insert_price_list_rate_if_missing", 1)
 
@@ -519,7 +536,6 @@
 		from erpnext.buying.doctype.purchase_order.purchase_order import update_status
 
 		make_stock_entry(target="_Test Warehouse - _TC", qty=10, rate=100)
-		from erpnext.stock.doctype.item.test_item import make_item
 		po_item = make_item("_Test Item for Drop Shipping", {"is_stock_item": 1, "delivered_by_supplier": 1})
 
 		dn_item = make_item("_Test Regular Item", {"is_stock_item": 1})
@@ -714,7 +730,6 @@
 
 	def test_serial_no_based_delivery(self):
 		frappe.set_value("Stock Settings", None, "automatically_set_serial_nos_based_on_fifo", 1)
-		from erpnext.stock.doctype.item.test_item import make_item
 		item = make_item("_Reserved_Serialized_Item", {"is_stock_item": 1,
 					"maintain_stock": 1,
 					"has_serial_no": 1,
@@ -835,7 +850,6 @@
 		self.assertRaises(frappe.LinkExistsError, so_doc.cancel)
 
 	def test_request_for_raw_materials(self):
-		from erpnext.stock.doctype.item.test_item import make_item
 		item = make_item("_Test Finished Item", {"is_stock_item": 1,
 			"maintain_stock": 1,
 			"valuation_rate": 500,
diff --git a/erpnext/selling/module_onboarding/selling/selling.json b/erpnext/selling/module_onboarding/selling/selling.json
index 10a33c9..160208f 100644
--- a/erpnext/selling/module_onboarding/selling/selling.json
+++ b/erpnext/selling/module_onboarding/selling/selling.json
@@ -19,7 +19,7 @@
  "documentation_url": "https://docs.erpnext.com/docs/user/manual/en/selling",
  "idx": 0,
  "is_complete": 0,
- "modified": "2020-06-01 13:35:16.100512",
+ "modified": "2020-07-08 14:05:37.669753",
  "modified_by": "Administrator",
  "module": "Selling",
  "name": "Selling",
@@ -47,8 +47,7 @@
    "step": "Selling Settings"
   }
  ],
- "subtitle": "Products, Sales, Analysis and more.",
+ "subtitle": "Products, Sales, Analysis, and more.",
  "success_message": "The Selling Module is all set up!",
- "title": "Let's Set Up the Selling Module.",
- "user_can_dismiss": 1
+ "title": "Let's Set Up the Selling Module."
 }
\ No newline at end of file
diff --git a/erpnext/selling/number_card/active_customers/active_customers.json b/erpnext/selling/number_card/active_customers/active_customers.json
new file mode 100644
index 0000000..3377634
--- /dev/null
+++ b/erpnext/selling/number_card/active_customers/active_customers.json
@@ -0,0 +1,21 @@
+{
+ "creation": "2020-07-20 20:17:16.653866",
+ "docstatus": 0,
+ "doctype": "Number Card",
+ "document_type": "Customer",
+ "dynamic_filters_json": "",
+ "filters_json": "[[\"Customer\",\"disabled\",\"=\",\"0\"]]",
+ "function": "Count",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "label": "Active Customers",
+ "modified": "2020-07-22 14:20:32.268103",
+ "modified_by": "Administrator",
+ "module": "Selling",
+ "name": "Active Customers",
+ "owner": "Administrator",
+ "show_percentage_stats": 1,
+ "stats_time_interval": "Monthly",
+ "type": "Document Type"
+}
\ No newline at end of file
diff --git a/erpnext/selling/number_card/annual_sales/annual_sales.json b/erpnext/selling/number_card/annual_sales/annual_sales.json
new file mode 100644
index 0000000..8746ee4
--- /dev/null
+++ b/erpnext/selling/number_card/annual_sales/annual_sales.json
@@ -0,0 +1,22 @@
+{
+ "aggregate_function_based_on": "base_net_total",
+ "creation": "2020-07-20 20:17:16.568132",
+ "docstatus": 0,
+ "doctype": "Number Card",
+ "document_type": "Sales Order",
+ "dynamic_filters_json": "[[\"Sales Order\",\"company\",\"=\",\"frappe.defaults.get_user_default(\\\"Company\\\")\"]]",
+ "filters_json": "[[\"Sales Order\",\"status\",\"not in\",[\"Draft\",\"Cancelled\",\"Closed\",null],false],[\"Sales Order\",\"docstatus\",\"=\",\"1\",false],[\"Sales Order\",\"modified\",\"Timespan\",\"this year\",false]]",
+ "function": "Sum",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "label": "Annual Sales",
+ "modified": "2020-07-22 16:56:33.747156",
+ "modified_by": "Administrator",
+ "module": "Selling",
+ "name": "Annual Sales",
+ "owner": "Administrator",
+ "show_percentage_stats": 1,
+ "stats_time_interval": "Monthly",
+ "type": "Document Type"
+}
\ No newline at end of file
diff --git a/erpnext/selling/number_card/sales_orders_to_bill/sales_orders_to_bill.json b/erpnext/selling/number_card/sales_orders_to_bill/sales_orders_to_bill.json
new file mode 100644
index 0000000..27fea45
--- /dev/null
+++ b/erpnext/selling/number_card/sales_orders_to_bill/sales_orders_to_bill.json
@@ -0,0 +1,21 @@
+{
+ "creation": "2020-07-20 20:17:16.625001",
+ "docstatus": 0,
+ "doctype": "Number Card",
+ "document_type": "Sales Order",
+ "dynamic_filters_json": "[[\"Sales Order\",\"company\",\"=\",\"frappe.defaults.get_user_default(\\\"Company\\\")\"]]",
+ "filters_json": "[[\"Sales Order\",\"status\",\"in\",[\"To Deliver and Bill\",\"To Bill\",null],false],[\"Sales Order\",\"docstatus\",\"=\",\"1\",false]]",
+ "function": "Count",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "label": "Sales Orders to Bill",
+ "modified": "2020-07-22 14:20:09.918626",
+ "modified_by": "Administrator",
+ "module": "Selling",
+ "name": "Sales Orders to Bill",
+ "owner": "Administrator",
+ "show_percentage_stats": 1,
+ "stats_time_interval": "Weekly",
+ "type": "Document Type"
+}
\ No newline at end of file
diff --git a/erpnext/selling/number_card/sales_orders_to_deliver/sales_orders_to_deliver.json b/erpnext/selling/number_card/sales_orders_to_deliver/sales_orders_to_deliver.json
new file mode 100644
index 0000000..6e19cf4
--- /dev/null
+++ b/erpnext/selling/number_card/sales_orders_to_deliver/sales_orders_to_deliver.json
@@ -0,0 +1,21 @@
+{
+ "creation": "2020-07-20 20:17:16.596857",
+ "docstatus": 0,
+ "doctype": "Number Card",
+ "document_type": "Sales Order",
+ "dynamic_filters_json": "[[\"Sales Order\",\"company\",\"=\",\"frappe.defaults.get_user_default(\\\"Company\\\")\"]]",
+ "filters_json": "[[\"Sales Order\",\"status\",\"in\",[\"To Deliver and Bill\",\"To Deliver\",null],false],[\"Sales Order\",\"docstatus\",\"=\",\"1\",false]]",
+ "function": "Count",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "label": "Sales Orders to Deliver",
+ "modified": "2020-07-22 14:19:28.833784",
+ "modified_by": "Administrator",
+ "module": "Selling",
+ "name": "Sales Orders to Deliver",
+ "owner": "Administrator",
+ "show_percentage_stats": 1,
+ "stats_time_interval": "Weekly",
+ "type": "Document Type"
+}
\ No newline at end of file
diff --git a/erpnext/selling/onboarding_step/setup_your_warehouse/setup_your_warehouse.json b/erpnext/selling/onboarding_step/setup_your_warehouse/setup_your_warehouse.json
index 557c905..9457dee 100644
--- a/erpnext/selling/onboarding_step/setup_your_warehouse/setup_your_warehouse.json
+++ b/erpnext/selling/onboarding_step/setup_your_warehouse/setup_your_warehouse.json
@@ -8,13 +8,13 @@
  "is_mandatory": 0,
  "is_single": 0,
  "is_skipped": 0,
- "modified": "2020-05-19 18:54:19.383397",
+ "modified": "2020-07-04 12:33:16.970031",
  "modified_by": "Administrator",
  "name": "Setup your Warehouse",
  "owner": "Administrator",
  "path": "Tree/Warehouse",
  "reference_document": "Warehouse",
  "show_full_form": 0,
- "title": "Setup your Warehouse",
+ "title": "Set up your Warehouse",
  "validate_action": 1
 }
\ No newline at end of file
diff --git a/erpnext/selling/page/point_of_sale/onscan.js b/erpnext/selling/page/point_of_sale/onscan.js
new file mode 100644
index 0000000..428dc75
--- /dev/null
+++ b/erpnext/selling/page/point_of_sale/onscan.js
@@ -0,0 +1 @@
+!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t()):e.onScan=t()}(this,function(){var d={attachTo:function(e,t){if(void 0!==e.scannerDetectionData)throw new Error("onScan.js is already initialized for DOM element "+e);var n={onScan:function(e,t){},onScanError:function(e){},onKeyProcess:function(e,t){},onKeyDetect:function(e,t){},onPaste:function(e,t){},keyCodeMapper:function(e){return d.decodeKeyEvent(e)},onScanButtonLongPress:function(){},scanButtonKeyCode:!1,scanButtonLongPressTime:500,timeBeforeScanTest:100,avgTimeByChar:30,minLength:6,suffixKeyCodes:[9,13],prefixKeyCodes:[],ignoreIfFocusOn:!1,stopPropagation:!1,preventDefault:!1,captureEvents:!1,reactToKeydown:!0,reactToPaste:!1,singleScanQty:1};return t=this._mergeOptions(n,t),e.scannerDetectionData={options:t,vars:{firstCharTime:0,lastCharTime:0,accumulatedString:"",testTimer:!1,longPressTimeStart:0,longPressed:!1}},!0===t.reactToPaste&&e.addEventListener("paste",this._handlePaste,t.captureEvents),!1!==t.scanButtonKeyCode&&e.addEventListener("keyup",this._handleKeyUp,t.captureEvents),!0!==t.reactToKeydown&&!1===t.scanButtonKeyCode||e.addEventListener("keydown",this._handleKeyDown,t.captureEvents),this},detachFrom:function(e){e.scannerDetectionData.options.reactToPaste&&e.removeEventListener("paste",this._handlePaste),!1!==e.scannerDetectionData.options.scanButtonKeyCode&&e.removeEventListener("keyup",this._handleKeyUp),e.removeEventListener("keydown",this._handleKeyDown),e.scannerDetectionData=void 0},getOptions:function(e){return e.scannerDetectionData.options},setOptions:function(e,t){switch(e.scannerDetectionData.options.reactToPaste){case!0:!1===t.reactToPaste&&e.removeEventListener("paste",this._handlePaste);break;case!1:!0===t.reactToPaste&&e.addEventListener("paste",this._handlePaste)}switch(e.scannerDetectionData.options.scanButtonKeyCode){case!1:!1!==t.scanButtonKeyCode&&e.addEventListener("keyup",this._handleKeyUp);break;default:!1===t.scanButtonKeyCode&&e.removeEventListener("keyup",this._handleKeyUp)}return e.scannerDetectionData.options=this._mergeOptions(e.scannerDetectionData.options,t),this._reinitialize(e),this},decodeKeyEvent:function(e){var t=this._getNormalizedKeyNum(e);switch(!0){case 48<=t&&t<=90:case 106<=t&&t<=111:if(void 0!==e.key&&""!==e.key)return e.key;var n=String.fromCharCode(t);switch(e.shiftKey){case!1:n=n.toLowerCase();break;case!0:n=n.toUpperCase()}return n;case 96<=t&&t<=105:return t-96}return""},simulate:function(e,t){return this._reinitialize(e),Array.isArray(t)?t.forEach(function(e){var t={};"object"!=typeof e&&"function"!=typeof e||null===e?t.keyCode=parseInt(e):t=e;var n=new KeyboardEvent("keydown",t);document.dispatchEvent(n)}):this._validateScanCode(e,t),this},_reinitialize:function(e){var t=e.scannerDetectionData.vars;t.firstCharTime=0,t.lastCharTime=0,t.accumulatedString=""},_isFocusOnIgnoredElement:function(e){var t=e.scannerDetectionData.options.ignoreIfFocusOn;if(!t)return!1;var n=document.activeElement;if(Array.isArray(t)){for(var a=0;a<t.length;a++)if(!0===n.matches(t[a]))return!0}else if(n.matches(t))return!0;return!1},_validateScanCode:function(e,t){var n,a=e.scannerDetectionData,i=a.options,o=a.options.singleScanQty,r=a.vars.firstCharTime,s=a.vars.lastCharTime,c={};switch(!0){case t.length<i.minLength:c={message:"Receieved code is shorter then minimal length"};break;case s-r>t.length*i.avgTimeByChar:c={message:"Receieved code was not entered in time"};break;default:return i.onScan.call(e,t,o),n=new CustomEvent("scan",{detail:{scanCode:t,qty:o}}),e.dispatchEvent(n),d._reinitialize(e),!0}return c.scanCode=t,c.scanDuration=s-r,c.avgTimeByChar=i.avgTimeByChar,c.minLength=i.minLength,i.onScanError.call(e,c),n=new CustomEvent("scanError",{detail:c}),e.dispatchEvent(n),d._reinitialize(e),!1},_mergeOptions:function(e,t){var n,a={};for(n in e)Object.prototype.hasOwnProperty.call(e,n)&&(a[n]=e[n]);for(n in t)Object.prototype.hasOwnProperty.call(t,n)&&(a[n]=t[n]);return a},_getNormalizedKeyNum:function(e){return e.which||e.keyCode},_handleKeyDown:function(e){var t=d._getNormalizedKeyNum(e),n=this.scannerDetectionData.options,a=this.scannerDetectionData.vars,i=!1;if(!1!==n.onKeyDetect.call(this,t,e)&&!d._isFocusOnIgnoredElement(this))if(!1===n.scanButtonKeyCode||t!=n.scanButtonKeyCode){switch(!0){case a.firstCharTime&&-1!==n.suffixKeyCodes.indexOf(t):e.preventDefault(),e.stopImmediatePropagation(),i=!0;break;case!a.firstCharTime&&-1!==n.prefixKeyCodes.indexOf(t):e.preventDefault(),e.stopImmediatePropagation(),i=!1;break;default:var o=n.keyCodeMapper.call(this,e);if(null===o)return;a.accumulatedString+=o,n.preventDefault&&e.preventDefault(),n.stopPropagation&&e.stopImmediatePropagation(),i=!1}a.firstCharTime||(a.firstCharTime=Date.now()),a.lastCharTime=Date.now(),a.testTimer&&clearTimeout(a.testTimer),i?(d._validateScanCode(this,a.accumulatedString),a.testTimer=!1):a.testTimer=setTimeout(d._validateScanCode,n.timeBeforeScanTest,this,a.accumulatedString),n.onKeyProcess.call(this,o,e)}else a.longPressed||(a.longPressTimer=setTimeout(n.onScanButtonLongPress,n.scanButtonLongPressTime,this),a.longPressed=!0)},_handlePaste:function(e){if(!d._isFocusOnIgnoredElement(this)){e.preventDefault(),oOptions.stopPropagation&&e.stopImmediatePropagation();var t=(event.clipboardData||window.clipboardData).getData("text");this.scannerDetectionData.options.onPaste.call(this,t,event);var n=this.scannerDetectionData.vars;n.firstCharTime=0,n.lastCharTime=0,d._validateScanCode(this,t)}},_handleKeyUp:function(e){d._isFocusOnIgnoredElement(this)||d._getNormalizedKeyNum(e)==this.scannerDetectionData.options.scanButtonKeyCode&&(clearTimeout(this.scannerDetectionData.vars.longPressTimer),this.scannerDetectionData.vars.longPressed=!1)},isScanInProgressFor:function(e){return 0<e.scannerDetectionData.vars.firstCharTime}};return d});
\ No newline at end of file
diff --git a/erpnext/selling/page/point_of_sale/point_of_sale.js b/erpnext/selling/page/point_of_sale/point_of_sale.js
index 7011cf9..2ce0b27 100644
--- a/erpnext/selling/page/point_of_sale/point_of_sale.js
+++ b/erpnext/selling/page/point_of_sale/point_of_sale.js
@@ -1,5 +1,6 @@
 /* global Clusterize */
-frappe.provide('erpnext.pos');
+frappe.provide('erpnext.PointOfSale');
+{% include "erpnext/selling/page/point_of_sale/pos_controller.js" %}
 frappe.provide('erpnext.queries');
 
 frappe.pages['point-of-sale'].on_page_load = function(wrapper) {
@@ -8,1988 +9,7 @@
 		title: __('Point of Sale'),
 		single_column: true
 	});
-
-	frappe.db.get_value('POS Settings', {name: 'POS Settings'}, 'is_online', (r) => {
-		if (r && !cint(r.use_pos_in_offline_mode)) {
-			// online
-			wrapper.pos = new erpnext.pos.PointOfSale(wrapper);
-			window.cur_pos = wrapper.pos;
-		} else {
-			// offline
-			frappe.flags.is_offline = true;
-			frappe.set_route('pos');
-		}
-	});
-};
-
-frappe.pages['point-of-sale'].refresh = function(wrapper) {
-	if (wrapper.pos) {
-		wrapper.pos.make_new_invoice();
-	}
-
-	if (frappe.flags.is_offline) {
-		frappe.set_route('pos');
-	}
-}
-
-erpnext.pos.PointOfSale = class PointOfSale {
-	constructor(wrapper) {
-		this.wrapper = $(wrapper).find('.layout-main-section');
-		this.page = wrapper.page;
-
-		const assets = [
-			'assets/erpnext/js/pos/clusterize.js',
-			'assets/erpnext/css/pos.css'
-		];
-
-		frappe.require(assets, () => {
-			this.make();
-		});
-	}
-
-	make() {
-		return frappe.run_serially([
-			() => frappe.dom.freeze(),
-			() => {
-				this.prepare_dom();
-				this.prepare_menu();
-				this.set_online_status();
-			},
-			() => this.make_new_invoice(),
-			() => {
-				if(!this.frm.doc.company) {
-					this.setup_company()
-						.then((company) => {
-							this.frm.doc.company = company;
-							this.get_pos_profile();
-						});
-				}
-			},
-			() => {
-				frappe.dom.unfreeze();
-			},
-			() => this.page.set_title(__('Point of Sale'))
-		]);
-	}
-
-	get_pos_profile() {
-		return frappe.xcall("erpnext.stock.get_item_details.get_pos_profile",
-			{'company': this.frm.doc.company})
-			.then((r) => {
-				if(r) {
-					this.frm.doc.pos_profile = r.name;
-					this.set_pos_profile_data()
-						.then(() => {
-							this.on_change_pos_profile();
-						});
-				} else {
-					this.raise_exception_for_pos_profile();
-				}
-		});
-	}
-
-	set_online_status() {
-		this.connection_status = false;
-		this.page.set_indicator(__("Offline"), "grey");
-		frappe.call({
-			method: "frappe.handler.ping",
-			callback: r => {
-				if (r.message) {
-					this.connection_status = true;
-					this.page.set_indicator(__("Online"), "green");
-				}
-			}
-		});
-	}
-
-	raise_exception_for_pos_profile() {
-		setTimeout(() => frappe.set_route('List', 'POS Profile'), 2000);
-		frappe.throw(__("POS Profile is required to use Point-of-Sale"));
-	}
-
-	prepare_dom() {
-		this.wrapper.append(`
-			<div class="pos">
-				<section class="cart-container">
-
-				</section>
-				<section class="item-container">
-
-				</section>
-			</div>
-		`);
-	}
-
-	make_cart() {
-		this.cart = new POSCart({
-			frm: this.frm,
-			wrapper: this.wrapper.find('.cart-container'),
-			events: {
-				on_customer_change: (customer) => {
-					this.frm.set_value('customer', customer);
-				},
-				on_field_change: (item_code, field, value, batch_no) => {
-					this.update_item_in_cart(item_code, field, value, batch_no);
-				},
-				on_numpad: (value) => {
-					if (value == __('Pay')) {
-						if (!this.payment) {
-							this.make_payment_modal();
-						} else {
-							this.frm.doc.payments.map(p => {
-								this.payment.dialog.set_value(p.mode_of_payment, p.amount);
-							});
-
-							this.payment.set_title();
-						}
-						this.payment.open_modal();
-					}
-				},
-				on_select_change: () => {
-					this.cart.numpad.set_inactive();
-					this.set_form_action();
-				},
-				get_item_details: (item_code) => {
-					return this.items.get(item_code);
-				},
-				get_loyalty_details: () => {
-					var me = this;
-					if (this.frm.doc.customer) {
-						frappe.call({
-							method: "erpnext.accounts.doctype.loyalty_program.loyalty_program.get_loyalty_program_details",
-							args: {
-								"customer": me.frm.doc.customer,
-								"expiry_date": me.frm.doc.posting_date,
-								"company": me.frm.doc.company,
-								"silent": true
-							},
-							callback: function(r) {
-								if (r.message.loyalty_program && r.message.loyalty_points) {
-									me.cart.events.set_loyalty_details(r.message, true);
-								}
-								if (!r.message.loyalty_program) {
-									var loyalty_details = {
-										loyalty_points: 0,
-										loyalty_program: '',
-										expense_account: '',
-										cost_center: ''
-									}
-									me.cart.events.set_loyalty_details(loyalty_details, false);
-								}
-							}
-						});
-					}
-				},
-				set_loyalty_details: (details, view_status) => {
-					if (view_status) {
-						this.cart.available_loyalty_points.$wrapper.removeClass("hide");
-					} else {
-						this.cart.available_loyalty_points.$wrapper.addClass("hide");
-					}
-					this.cart.available_loyalty_points.set_value(details.loyalty_points);
-					this.cart.available_loyalty_points.refresh_input();
-					this.frm.set_value("loyalty_program", details.loyalty_program);
-					this.frm.set_value("loyalty_redemption_account", details.expense_account);
-					this.frm.set_value("loyalty_redemption_cost_center", details.cost_center);
-				}
-			}
-		});
-
-		frappe.ui.form.on('Sales Invoice', 'selling_price_list', (frm) => {
-			if(this.items && frm.doc.pos_profile) {
-				this.items.reset_items();
-			}
-		})
-	}
-
-	toggle_editing(flag) {
-		let disabled;
-		if (flag !== undefined) {
-			disabled = !flag;
-		} else {
-			disabled = this.frm.doc.docstatus == 1 ? true: false;
-		}
-		const pointer_events = disabled ? 'none' : 'inherit';
-
-		this.wrapper.find('input, button, select').prop("disabled", disabled);
-		this.wrapper.find('.number-pad-container').toggleClass("hide", disabled);
-
-		this.wrapper.find('.cart-container').css('pointer-events', pointer_events);
-		this.wrapper.find('.item-container').css('pointer-events', pointer_events);
-
-		this.page.clear_actions();
-	}
-
-	make_items() {
-		this.items = new POSItems({
-			wrapper: this.wrapper.find('.item-container'),
-			frm: this.frm,
-			events: {
-				update_cart: (item, field, value) => {
-					if(!this.frm.doc.customer) {
-						frappe.throw(__('Please select a customer'));
-					}
-					this.update_item_in_cart(item, field, value);
-					this.cart && this.cart.unselect_all();
-				}
-			}
-		});
-	}
-
-	update_item_in_cart(item_code, field='qty', value=1, batch_no) {
-		frappe.dom.freeze();
-		if(this.cart.exists(item_code, batch_no)) {
-			const search_field = batch_no ? 'batch_no' : 'item_code';
-			const search_value = batch_no || item_code;
-			const item = this.frm.doc.items.find(i => i[search_field] === search_value);
-			frappe.flags.hide_serial_batch_dialog = false;
-
-			if (typeof value === 'string' && !in_list(['serial_no', 'batch_no'], field)) {
-				// value can be of type '+1' or '-1'
-				value = item[field] + flt(value);
-			}
-
-			if(field === 'serial_no') {
-				value = item.serial_no + '\n'+ value;
-			}
-
-			// if actual_batch_qty and actual_qty if there is only one batch. In such
-			// a case, no point showing the dialog
-			const show_dialog = item.has_serial_no || item.has_batch_no;
-
-			if (show_dialog && field == 'qty' && ((!item.batch_no && item.has_batch_no) ||
-				(item.has_serial_no) || (item.actual_batch_qty != item.actual_qty)) ) {
-				this.select_batch_and_serial_no(item);
-			} else {
-				this.update_item_in_frm(item, field, value)
-					.then(() => {
-						frappe.dom.unfreeze();
-						frappe.run_serially([
-							() => {
-								let items = this.frm.doc.items.map(item => item.name);
-								if (items && items.length > 0 && items.includes(item.name)) {
-									this.frm.doc.items.forEach(item_row => {
-										// update cart
-										this.on_qty_change(item_row);
-									});
-								} else {
-									this.on_qty_change(item);
-								}
-							},
-							() => this.post_qty_change(item)
-						]);
-					});
-			}
-			return;
-		}
-
-		let args = { item_code: item_code };
-		if (in_list(['serial_no', 'batch_no'], field)) {
-			args[field] = value;
-		}
-
-		// add to cur_frm
-		const item = this.frm.add_child('items', args);
-		frappe.flags.hide_serial_batch_dialog = true;
-
-		frappe.run_serially([
-			() => {
-				return this.frm.script_manager.trigger('item_code', item.doctype, item.name)
-					.then(() => {
-						this.frm.script_manager.trigger('qty', item.doctype, item.name)
-							.then(() => {
-								frappe.run_serially([
-									() => {
-										let items = this.frm.doc.items.map(i => i.name);
-										if (items && items.length > 0 && items.includes(item.name)) {
-											this.frm.doc.items.forEach(item_row => {
-												// update cart
-												this.on_qty_change(item_row);
-											});
-										} else {
-											this.on_qty_change(item);
-										}
-									},
-									() => this.post_qty_change(item)
-								]);
-							});
-					});
-			},
-			() => {
-				const show_dialog = item.has_serial_no || item.has_batch_no;
-
-				// if actual_batch_qty and actual_qty if then there is only one batch. In such
-				// a case, no point showing the dialog
-				if (show_dialog && field == 'qty' && ((!item.batch_no && item.has_batch_no) ||
-					(item.has_serial_no) || (item.actual_batch_qty != item.actual_qty)) ) {
-					// check has serial no/batch no and update cart
-					this.select_batch_and_serial_no(item);
-				}
-			}
-		]);
-	}
-
-	on_qty_change(item) {
-		frappe.run_serially([
-			() => this.update_cart_data(item),
-		]);
-	}
-
-	post_qty_change(item) {
-		this.cart.update_taxes_and_totals();
-		this.cart.update_grand_total();
-		this.cart.update_qty_total();
-		this.cart.scroll_to_item(item.item_code);
-		this.set_form_action();
-	}
-
-	select_batch_and_serial_no(row) {
-		frappe.dom.unfreeze();
-
-		erpnext.show_serial_batch_selector(this.frm, row, () => {
-			this.frm.doc.items.forEach(item => {
-				this.update_item_in_frm(item, 'qty', item.qty)
-					.then(() => {
-						// update cart
-						frappe.run_serially([
-							() => {
-								if (item.qty === 0) {
-									frappe.model.clear_doc(item.doctype, item.name);
-								}
-							},
-							() => this.update_cart_data(item),
-							() => this.post_qty_change(item)
-						]);
-					});
-			})
-		}, () => {
-			this.on_close(row);
-		}, true);
-	}
-
-	on_close(item) {
-		if (!this.cart.exists(item.item_code, item.batch_no) && item.qty) {
-			frappe.model.clear_doc(item.doctype, item.name);
-		}
-	}
-
-	update_cart_data(item) {
-		this.cart.add_item(item);
-		frappe.dom.unfreeze();
-	}
-
-	update_item_in_frm(item, field, value) {
-		if (field == 'qty' && value < 0) {
-			frappe.msgprint(__("Quantity must be positive"));
-			value = item.qty;
-		} else {
-			if (in_list(["qty", "serial_no", "batch"], field)) {
-				item[field] = value;
-				if (field == "serial_no" && value) {
-					let serial_nos = value.split("\n");
-					item["qty"] = serial_nos.filter(d => {
-						return d!=="";
-					}).length;
-				}
-			} else {
-				return frappe.model.set_value(item.doctype, item.name, field, value);
-			}
-		}
-
-		return this.frm.script_manager.trigger('qty', item.doctype, item.name)
-			.then(() => {
-				if (field === 'qty' && item.qty === 0) {
-					frappe.model.clear_doc(item.doctype, item.name);
-				}
-			})
-
-		return Promise.resolve();
-	}
-
-	make_payment_modal() {
-		this.payment = new Payment({
-			frm: this.frm,
-			events: {
-				submit_form: () => {
-					this.submit_sales_invoice();
-				}
-			}
-		});
-	}
-
-	submit_sales_invoice() {
-		this.frm.savesubmit()
-			.then((r) => {
-				if (r && r.doc) {
-					this.frm.doc.docstatus = r.doc.docstatus;
-					frappe.show_alert({
-						indicator: 'green',
-						message: __(`Sales invoice ${r.doc.name} created succesfully`)
-					});
-
-					this.toggle_editing();
-					this.set_form_action();
-					this.set_primary_action_in_modal();
-				}
-			});
-	}
-
-	set_primary_action_in_modal() {
-		if (!this.frm.msgbox) {
-			this.frm.msgbox = frappe.msgprint(
-				`<a class="btn btn-primary" onclick="cur_frm.print_preview.printit(true)" style="margin-right: 5px;">
-					${__('Print')}</a>
-				<a class="btn btn-default">
-					${__('New')}</a>`
-			);
-
-			$(this.frm.msgbox.body).find('.btn-default').on('click', () => {
-				this.frm.msgbox.hide();
-				this.make_new_invoice();
-			})
-		}
-	}
-
-	change_pos_profile() {
-		return new Promise((resolve) => {
-			const on_submit = ({ company, pos_profile, set_as_default }) => {
-				if (pos_profile) {
-					this.pos_profile = pos_profile;
-				}
-
-				if (set_as_default) {
-					frappe.call({
-						method: "erpnext.accounts.doctype.pos_profile.pos_profile.set_default_profile",
-						args: {
-							'pos_profile': pos_profile,
-							'company': company
-						}
-					}).then(() => {
-						this.on_change_pos_profile();
-					});
-				} else {
-					this.on_change_pos_profile();
-				}
-			}
-
-
-			let me = this;
-
-			var dialog = frappe.prompt([{
-					fieldtype: 'Link',
-					label: __('Company'),
-					options: 'Company',
-					fieldname: 'company',
-					default: me.frm.doc.company,
-					reqd: 1,
-					onchange: function(e) {
-							me.get_default_pos_profile(this.value).then((r) => {
-								dialog.set_value('pos_profile', (r && r.name)? r.name : '');
-							});
-						}
-					},
-					{
-					fieldtype: 'Link',
-					label: __('POS Profile'),
-					options: 'POS Profile',
-					fieldname: 'pos_profile',
-					default: me.frm.doc.pos_profile,
-					reqd: 1,
-					get_query: () => {
-						return {
-							query: 'erpnext.accounts.doctype.pos_profile.pos_profile.pos_profile_query',
-							filters: {
-								company: dialog.get_value('company')
-							}
-						};
-					}
-				}, {
-					fieldtype: 'Check',
-					label: __('Set as default'),
-					fieldname: 'set_as_default'
-				}],
-				on_submit,
-				__('Select POS Profile')
-			);
-		});
-	}
-
-	on_change_pos_profile() {
-		return frappe.run_serially([
-			() => this.make_sales_invoice_frm(),
-			() => {
-				this.frm.doc.pos_profile = this.pos_profile;
-				this.set_pos_profile_data()
-					.then(() => {
-						this.reset_cart();
-						if (this.items) {
-							this.items.reset_items();
-						}
-					});
-			}
-		]);
-	}
-
-	get_default_pos_profile(company) {
-		return frappe.xcall("erpnext.stock.get_item_details.get_pos_profile",
-			{'company': company})
-	}
-
-	setup_company() {
-		return new Promise(resolve => {
-			if(!this.frm.doc.company) {
-				frappe.prompt({fieldname:"company", options: "Company", fieldtype:"Link",
-					label: __("Select Company"), reqd: 1}, (data) => {
-						this.company = data.company;
-						resolve(this.company);
-				}, __("Select Company"));
-			} else {
-				resolve();
-			}
-		})
-	}
-
-	make_new_invoice() {
-		return frappe.run_serially([
-			() => this.make_sales_invoice_frm(),
-			() => this.set_pos_profile_data(),
-			() => {
-				if (this.cart) {
-					this.cart.frm = this.frm;
-					this.cart.reset();
-					this.cart.reset_pos_field_value();
-				} else {
-					this.make_items();
-					this.make_cart();
-				}
-				this.toggle_editing(true);
-			},
-		]);
-	}
-
-	reset_cart() {
-		this.cart.frm = this.frm;
-		this.cart.reset();
-		this.items.reset_search_field();
-	}
-
-	make_sales_invoice_frm() {
-		const doctype = 'Sales Invoice';
-		return new Promise(resolve => {
-			if (this.frm) {
-				this.frm = get_frm(this.frm);
-				if(this.company) {
-					this.frm.doc.company = this.company;
-				}
-
-				resolve();
-			} else {
-				frappe.model.with_doctype(doctype, () => {
-					this.frm = get_frm();
-					resolve();
-				});
-			}
-		});
-
-		function get_frm(_frm) {
-			const page = $('<div>');
-			const frm = _frm || new frappe.ui.form.Form(doctype, page, false);
-			const name = frappe.model.make_new_doc_and_get_name(doctype, true);
-			frm.refresh(name);
-			frm.doc.items = [];
-			frm.doc.is_pos = 1;
-
-			return frm;
-		}
-	}
-
-	set_pos_profile_data() {
-		if (this.company) {
-			this.frm.doc.company = this.company;
-		}
-
-		if (!this.frm.doc.company) {
-			return;
-		}
-
-		return new Promise(resolve => {
-			return this.frm.call({
-				doc: this.frm.doc,
-				method: "set_missing_values",
-			}).then((r) => {
-				if(!r.exc) {
-					if (!this.frm.doc.pos_profile) {
-						frappe.dom.unfreeze();
-						this.raise_exception_for_pos_profile();
-					}
-					this.frm.script_manager.trigger("update_stock");
-					frappe.model.set_default_values(this.frm.doc);
-					this.frm.cscript.calculate_taxes_and_totals();
-
-					if (r.message) {
-						this.frm.meta.default_print_format = r.message.print_format || "";
-						this.frm.allow_edit_rate = r.message.allow_edit_rate;
-						this.frm.allow_edit_discount = r.message.allow_edit_discount;
-						this.frm.doc.campaign = r.message.campaign;
-						this.frm.allow_print_before_pay = r.message.allow_print_before_pay;
-					}
-				}
-
-				resolve();
-			});
-		});
-	}
-
-	prepare_menu() {
-		var me = this;
-		this.page.clear_menu();
-
-		this.page.add_menu_item(__("Form View"), function () {
-			frappe.model.sync(me.frm.doc);
-			frappe.set_route("Form", me.frm.doc.doctype, me.frm.doc.name);
-		});
-
-		this.page.add_menu_item(__("POS Profile"), function () {
-			frappe.set_route('List', 'POS Profile');
-		});
-
-		this.page.add_menu_item(__('POS Settings'), function() {
-			frappe.set_route('Form', 'POS Settings');
-		});
-
-		this.page.add_menu_item(__('Change POS Profile'), function() {
-			me.change_pos_profile();
-		});
-		this.page.add_menu_item(__('Close the POS'), function() {
-			var voucher = frappe.model.get_new_doc('POS Closing Voucher');
-			voucher.pos_profile = me.frm.doc.pos_profile;
-			voucher.user = frappe.session.user;
-			voucher.company = me.frm.doc.company;
-			voucher.period_start_date = me.frm.doc.posting_date;
-			voucher.period_end_date = me.frm.doc.posting_date;
-			voucher.posting_date = me.frm.doc.posting_date;
-			frappe.set_route('Form', 'POS Closing Voucher', voucher.name);
-		});
-	}
-
-	set_form_action() {
-		if(this.frm.doc.docstatus == 1 || (this.frm.allow_print_before_pay == 1 && this.frm.doc.items.length > 0)){
-			this.page.set_secondary_action(__("Print"), async() => {
-				if(this.frm.doc.docstatus != 1 ){
-					await this.frm.save();
-				}
-				this.frm.print_preview.printit(true);
-			});
-		}
-		if(this.frm.doc.items.length == 0){
-			this.page.clear_secondary_action();
-		}
-
-		if (this.frm.doc.docstatus == 1) {
-			this.page.set_primary_action(__("New"), () => {
-				this.make_new_invoice();
-			});
-			this.page.add_menu_item(__("Email"), () => {
-				this.frm.email_doc();
-			});
-		}
-	}
-};
-
-const [Qty,Disc,Rate,Del,Pay] = [__("Qty"), __('Disc'), __('Rate'), __('Del'), __('Pay')];
-
-class POSCart {
-	constructor({frm, wrapper, events}) {
-		this.frm = frm;
-		this.item_data = {};
-		this.wrapper = wrapper;
-		this.events = events;
-		this.make();
-		this.bind_events();
-	}
-
-	make() {
-		this.make_dom();
-		this.make_customer_field();
-		this.make_pos_fields();
-		this.make_loyalty_points();
-		this.make_numpad();
-	}
-
-	make_dom() {
-		this.wrapper.append(`
-			<div class="pos-cart">
-				<div class="customer-field">
-				</div>
-				<div class="pos-field-section" style="margin-bottom:12px; display:none">
-					<a class="h6 uppercase more-fields-section" disabled> ${__("More Information")} </a>
-					<i class="octicon octicon-chevron-down pos-fields-octicon collapse-indicator"
-						style="color:#cacaca; cursor: pointer"></i>
-					<div class="pos-fields" style ="margin-top:12px">
-					</div>
-				</div>
-				<div class="cart-wrapper">
-					<div class="list-item-table">
-						<div class="list-item list-item--head">
-							<div class="list-item__content list-item__content--flex-1.5 text-muted">${__('Item Name')}</div>
-							<div class="list-item__content text-muted text-right">${__('Quantity')}</div>
-							<div class="list-item__content text-muted text-right">${__('Discount')}</div>
-							<div class="list-item__content text-muted text-right">${__('Rate')}</div>
-						</div>
-						<div class="cart-items">
-							<div class="empty-state">
-								<span>${__('No Items added to cart')}</span>
-							</div>
-						</div>
-						<div class="taxes-and-totals">
-							${this.get_taxes_and_totals()}
-						</div>
-						<div class="discount-amount">`+
-						(!this.frm.allow_edit_discount ? `` : `${this.get_discount_amount()}`)+
-						`</div>
-						<div class="grand-total">
-							${this.get_grand_total()}
-						</div>
-						<div class="quantity-total">
-							${this.get_item_qty_total()}
-						</div>
-					</div>
-				</div>
-				<div class="row">
-					<div class="number-pad-container col-sm-6"></div>
-					<div class="col-sm-6 loyalty-program-section">
-						<div class="loyalty-program-field"> </div>
-					</div>
-				</div>
-			</div>
-		`);
-
-
-		this.$cart_items = this.wrapper.find('.cart-items');
-		this.$empty_state = this.wrapper.find('.cart-items .empty-state');
-		this.$taxes_and_totals = this.wrapper.find('.taxes-and-totals');
-		this.$discount_amount = this.wrapper.find('.discount-amount');
-		this.$grand_total = this.wrapper.find('.grand-total');
-		this.$qty_total = this.wrapper.find('.quantity-total');
-		// this.$loyalty_button = this.wrapper.find('.loyalty-button');
-
-		// this.$loyalty_button.on('click', () => {
-		// 	this.loyalty_button.show();
-		// })
-
-		this.toggle_taxes_and_totals(false);
-		this.$grand_total.on('click', () => {
-			this.toggle_taxes_and_totals();
-		});
-	}
-
-	reset() {
-		this.$cart_items.find('.list-item').remove();
-		this.$empty_state.show();
-		this.$taxes_and_totals.html(this.get_taxes_and_totals());
-		this.numpad && this.numpad.reset_value();
-		this.customer_field.set_value("");
-		this.frm.msgbox = "";
-
-		let total_item_qty = 0.0;
-		this.frm.set_value("pos_total_qty",total_item_qty);
-
-		this.$discount_amount.find('input:text').val('');
-		this.wrapper.find('.grand-total-value').text(
-			format_currency(this.frm.doc.grand_total, this.frm.currency));
-		this.wrapper.find('.rounded-total-value').text(
-			format_currency(this.frm.doc.rounded_total, this.frm.currency));
-		this.$qty_total.find(".quantity-total").text(total_item_qty);
-
-		const customer = this.frm.doc.customer;
-		this.customer_field.set_value(customer);
-
-		if (this.numpad) {
-			const disable_btns = this.disable_numpad_control()
-			const enable_btns = [__('Rate'), __('Disc')]
-
-			if (disable_btns) {
-				enable_btns.filter(btn => !disable_btns.includes(btn))
-			}
-
-			this.numpad.enable_buttons(enable_btns);
-		}
-	}
-
-	reset_pos_field_value() {
-		let value = '';
-		if (this.custom_pos_fields) {
-			this.custom_pos_fields.forEach(r => {
-				value = this.frm.doc[r.fieldname] || r.default_value || '';
-
-				if (this.fields) {
-					this.fields[r.fieldname].set_value(value);
-				}
-			})
-		}
-
-		this.wrapper.find('.pos-fields').toggle(false);
-		this.wrapper.find('.pos-fields-octicon').toggle(true);
-	}
-
-	get_grand_total() {
-		let total = this.get_total_template('Grand Total', 'grand-total-value');
-
-		if (!cint(frappe.sys_defaults.disable_rounded_total)) {
-			total += this.get_total_template('Rounded Total', 'rounded-total-value');
-		}
-
-		return total;
-	}
-
-	get_item_qty_total() {
-		let total = this.get_total_template('Total Qty', 'quantity-total');
-		return total;
-	}
-
-	get_total_template(label, class_name) {
-		return `
-			<div class="list-item">
-				<div class="list-item__content text-muted">${__(label)}</div>
-				<div class="list-item__content list-item__content--flex-2 ${class_name}">0.00</div>
-			</div>
-		`;
-	}
-
-	get_discount_amount() {
-		const get_currency_symbol = window.get_currency_symbol;
-
-		return `
-			<div class="list-item">
-				<div class="list-item__content list-item__content--flex-2 text-muted">${__('Discount')}</div>
-				<div class="list-item__content discount-inputs">
-					<input type="text"
-						class="form-control additional_discount_percentage text-right"
-						placeholder="% 0.00"
-					>
-					<input type="text"
-						class="form-control discount_amount text-right"
-						placeholder="${get_currency_symbol(this.frm.doc.currency)} 0.00"
-					>
-				</div>
-			</div>
-		`;
-	}
-
-	get_taxes_and_totals() {
-		return `
-			<div class="list-item">
-				<div class="list-item__content list-item__content--flex-2 text-muted">${__('Net Total')}</div>
-				<div class="list-item__content net-total">0.00</div>
-			</div>
-			<div class="list-item">
-				<div class="list-item__content list-item__content--flex-2 text-muted">${__('Taxes')}</div>
-				<div class="list-item__content taxes">0.00</div>
-			</div>
-		`;
-	}
-
-	toggle_taxes_and_totals(flag) {
-		if (flag !== undefined) {
-			this.tax_area_is_shown = flag;
-		} else {
-			this.tax_area_is_shown = !this.tax_area_is_shown;
-		}
-
-		this.$taxes_and_totals.toggle(this.tax_area_is_shown);
-		this.$discount_amount.toggle(this.tax_area_is_shown);
-	}
-
-	update_taxes_and_totals() {
-		if (!this.frm.doc.taxes) { return; }
-
-		const currency = this.frm.doc.currency;
-		this.frm.refresh_field('taxes');
-
-		// Update totals
-		this.$taxes_and_totals.find('.net-total')
-			.html(format_currency(this.frm.doc.total, currency));
-
-		// Update taxes
-		const taxes_html = this.frm.doc.taxes.map(tax => {
-			return `
-				<div>
-					<span>${tax.description}</span>
-					<span class="text-right bold">
-						${format_currency(tax.tax_amount, currency)}
-					</span>
-				</div>
-			`;
-		}).join("");
-		this.$taxes_and_totals.find('.taxes').html(taxes_html);
-	}
-
-	update_grand_total() {
-		this.$grand_total.find('.grand-total-value').text(
-			format_currency(this.frm.doc.grand_total, this.frm.currency)
-		);
-
-		this.$grand_total.find('.rounded-total-value').text(
-			format_currency(this.frm.doc.rounded_total, this.frm.currency)
-		);
-	}
-
-	update_qty_total() {
-		var total_item_qty = 0;
-		$.each(this.frm.doc["items"] || [], function (i, d) {
-				if (d.qty > 0) {
-					total_item_qty += d.qty;
-				}
-		});
-		this.$qty_total.find('.quantity-total').text(total_item_qty);
-		this.frm.set_value("pos_total_qty",total_item_qty);
-	}
-
-	make_customer_field() {
-		this.customer_field = frappe.ui.form.make_control({
-			df: {
-				fieldtype: 'Link',
-				label: 'Customer',
-				fieldname: 'customer',
-				options: 'Customer',
-				reqd: 1,
-				get_query: function() {
-					return {
-						query: 'erpnext.controllers.queries.customer_query'
-					}
-				},
-				onchange: () => {
-					this.events.on_customer_change(this.customer_field.get_value());
-					this.events.get_loyalty_details();
-				}
-			},
-			parent: this.wrapper.find('.customer-field'),
-			render_input: true
-		});
-
-		this.customer_field.set_value(this.frm.doc.customer);
-	}
-
-	make_pos_fields() {
-		const me = this;
-
-		this.fields = {};
-		this.wrapper.find('.pos-fields-octicon, .more-fields-section').click(() => {
-			this.wrapper.find('.pos-fields').toggle();
-			this.wrapper.find('.pos-fields-octicon').toggleClass('octicon-chevron-down').toggleClass('octicon-chevron-up');
-		});
-		this.wrapper.find('.pos-fields').toggle(false);
-
-		return new Promise(res => {
-			frappe.call({
-				method: "erpnext.selling.page.point_of_sale.point_of_sale.get_pos_fields",
-				freeze: true,
-			}).then(r => {
-				if(r.message.length) {
-					this.wrapper.find('.pos-field-section').css('display','block');
-					this.custom_pos_fields = r.message;
-					if (r.message.length < 3) {
-						this.wrapper.find('.pos-fields').toggle(true);
-						this.wrapper.find('.pos-fields-octicon').toggleClass('octicon-chevron-down').toggleClass('octicon-chevron-up');
-					}
-
-					r.message.forEach(field => {
-						this.fields[field.fieldname] = frappe.ui.form.make_control({
-							df: {
-								fieldtype: field.fieldtype,
-								label: field.label,
-								fieldname: field.fieldname,
-								options: field.options,
-								reqd: field.reqd || 0,
-								read_only: field.read_only || 0,
-								default: field.default_value,
-								onchange: function() {
-									if (this.value) {
-										me.frm.set_value(this.df.fieldname, this.value);
-									}
-								},
-								get_query: () => {
-									return this.get_query_for_pos_fields(field.fieldname)
-								},
-							},
-							parent: this.wrapper.find('.pos-fields'),
-							render_input: true
-						});
-
-						if (this.frm.doc[field.fieldname]) {
-							this.fields[field.fieldname].set_value(this.frm.doc[field.fieldname]);
-						}
-					});
-				}
-			});
-		});
-	}
-
-	get_query_for_pos_fields(field) {
-		if (this.frm.fields_dict && this.frm.fields_dict[field]
-			&& this.frm.fields_dict[field].get_query) {
-			return this.frm.fields_dict[field].get_query(this.frm.doc);
-		}
-	}
-
-	make_loyalty_points() {
-		this.available_loyalty_points = frappe.ui.form.make_control({
-			df: {
-				fieldtype: 'Int',
-				label: 'Available Loyalty Points',
-				read_only: 1,
-				fieldname: 'available_loyalty_points'
-			},
-			parent: this.wrapper.find('.loyalty-program-field')
-		});
-		this.available_loyalty_points.set_value(this.frm.doc.loyalty_points);
-	}
-
-
-	disable_numpad_control() {
-		let disabled_btns = [];
-		if(!this.frm.allow_edit_rate) {
-			disabled_btns.push(__('Rate'));
-		}
-		if(!this.frm.allow_edit_discount) {
-			disabled_btns.push(__('Disc'));
-		}
-		return disabled_btns;
-	}
-
-
-	make_numpad() {
-
-		var pay_class = {}
-		pay_class[__('Pay')]='brand-primary'
-		this.numpad = new NumberPad({
-			button_array: [
-				[1, 2, 3, Qty],
-				[4, 5, 6, Disc],
-				[7, 8, 9, Rate],
-				[Del, 0, '.', Pay]
-			],
-			add_class: pay_class,
-			disable_highlight: [Qty, Disc, Rate, Pay],
-			reset_btns: [Qty, Disc, Rate, Pay],
-			del_btn: Del,
-			disable_btns: this.disable_numpad_control(),
-			wrapper: this.wrapper.find('.number-pad-container'),
-			onclick: (btn_value) => {
-				// on click
-
-				if (!this.selected_item && btn_value !== Pay) {
-					frappe.show_alert({
-						indicator: 'red',
-						message: __('Please select an item in the cart')
-					});
-					return;
-				}
-				if ([Qty, Disc, Rate].includes(btn_value)) {
-					this.set_input_active(btn_value);
-				} else if (btn_value !== Pay) {
-					if (!this.selected_item.active_field) {
-						frappe.show_alert({
-							indicator: 'red',
-							message: __('Please select a field to edit from numpad')
-						});
-						return;
-					}
-
-					if (this.selected_item.active_field == 'discount_percentage' && this.numpad.get_value() > cint(100)) {
-						frappe.show_alert({
-							indicator: 'red',
-							message: __('Discount amount cannot be greater than 100%')
-						});
-						this.numpad.reset_value();
-					} else {
-						const item_code = unescape(this.selected_item.attr('data-item-code'));
-						const batch_no = this.selected_item.attr('data-batch-no');
-						const field = this.selected_item.active_field;
-						const value = this.numpad.get_value();
-
-						this.events.on_field_change(item_code, field, value, batch_no);
-					}
-				}
-
-				this.events.on_numpad(btn_value);
-			}
-		});
-	}
-
-	set_input_active(btn_value) {
-		this.selected_item.removeClass('qty disc rate');
-
-		this.numpad.set_active(btn_value);
-		if (btn_value === Qty) {
-			this.selected_item.addClass('qty');
-			this.selected_item.active_field = 'qty';
-		} else if (btn_value == Disc) {
-			this.selected_item.addClass('disc');
-			this.selected_item.active_field = 'discount_percentage';
-		} else if (btn_value == Rate) {
-			this.selected_item.addClass('rate');
-			this.selected_item.active_field = 'rate';
-		}
-	}
-
-	add_item(item) {
-		this.$empty_state.hide();
-
-		if (this.exists(item.item_code, item.batch_no)) {
-			// update quantity
-			this.update_item(item);
-		} else if (flt(item.qty) > 0.0) {
-			// add to cart
-			const $item = $(this.get_item_html(item));
-			$item.appendTo(this.$cart_items);
-		}
-		this.highlight_item(item.item_code);
-	}
-
-	update_item(item) {
-		const item_selector = item.batch_no ?
-			`[data-batch-no="${item.batch_no}"]` : `[data-item-code="${escape(item.item_code)}"]`;
-
-		const $item = this.$cart_items.find(item_selector);
-
-		if(item.qty > 0) {
-			const is_stock_item = this.get_item_details(item.item_code).is_stock_item;
-			const indicator_class = (!is_stock_item || item.actual_qty >= item.qty) ? 'green' : 'red';
-			const remove_class = indicator_class == 'green' ? 'red' : 'green';
-
-			$item.find('.quantity input').val(item.qty);
-			$item.find('.discount').text(item.discount_percentage + '%');
-			$item.find('.rate').text(format_currency(item.rate, this.frm.doc.currency));
-			$item.addClass(indicator_class);
-			$item.removeClass(remove_class);
-		} else {
-			$item.remove();
-		}
-	}
-
-	get_item_html(item) {
-		const is_stock_item = this.get_item_details(item.item_code).is_stock_item;
-		const rate = format_currency(item.rate, this.frm.doc.currency);
-		const indicator_class = (!is_stock_item || item.actual_qty >= item.qty) ? 'green' : 'red';
-		const batch_no = item.batch_no || '';
-
-		return `
-			<div class="list-item indicator ${indicator_class}" data-item-code="${escape(item.item_code)}"
-				data-batch-no="${batch_no}" title="Item: ${item.item_name}  Available Qty: ${item.actual_qty} ${item.stock_uom}">
-				<div class="item-name list-item__content list-item__content--flex-1.5 ellipsis">
-					${item.item_name}
-				</div>
-				<div class="quantity list-item__content text-right">
-					${get_quantity_html(item.qty)}
-				</div>
-				<div class="discount list-item__content text-right">
-					${item.discount_percentage}%
-				</div>
-				<div class="rate list-item__content text-right">
-					${rate}
-				</div>
-			</div>
-		`;
-
-		function get_quantity_html(value) {
-			return `
-				<div class="input-group input-group-xs">
-					<span class="input-group-btn">
-						<button class="btn btn-default btn-xs" data-action="increment">+</button>
-					</span>
-
-					<input class="form-control" type="number" value="${value}">
-
-					<span class="input-group-btn">
-						<button class="btn btn-default btn-xs" data-action="decrement">-</button>
-					</span>
-				</div>
-			`;
-		}
-	}
-
-	get_item_details(item_code) {
-		if (!this.item_data[item_code]) {
-			this.item_data[item_code] = this.events.get_item_details(item_code);
-		}
-
-		return this.item_data[item_code];
-	}
-
-	exists(item_code, batch_no) {
-		const is_exists = batch_no ?
-			`[data-batch-no="${batch_no}"]` : `[data-item-code="${escape(item_code)}"]`;
-
-		let $item = this.$cart_items.find(is_exists);
-
-		return $item.length > 0;
-	}
-
-	highlight_item(item_code) {
-		const $item = this.$cart_items.find(`[data-item-code="${escape(item_code)}"]`);
-		$item.addClass('highlight');
-		setTimeout(() => $item.removeClass('highlight'), 1000);
-	}
-
-	scroll_to_item(item_code) {
-		const $item = this.$cart_items.find(`[data-item-code="${escape(item_code)}"]`);
-		if ($item.length === 0) return;
-		const scrollTop = $item.offset().top - this.$cart_items.offset().top + this.$cart_items.scrollTop();
-		this.$cart_items.animate({ scrollTop });
-	}
-
-	bind_events() {
-		const me = this;
-		const events = this.events;
-
-		// quantity change
-		this.$cart_items.on('click',
-			'[data-action="increment"], [data-action="decrement"]', function() {
-				const $btn = $(this);
-				const $item = $btn.closest('.list-item[data-item-code]');
-				const item_code = unescape($item.attr('data-item-code'));
-				const action = $btn.attr('data-action');
-
-				if(action === 'increment') {
-					events.on_field_change(item_code, 'qty', '+1');
-				} else if(action === 'decrement') {
-					events.on_field_change(item_code, 'qty', '-1');
-				}
-			});
-
-		this.$cart_items.on('change', '.quantity input', function() {
-			const $input = $(this);
-			const $item = $input.closest('.list-item[data-item-code]');
-			const item_code = unescape($item.attr('data-item-code'));
-			events.on_field_change(item_code, 'qty', flt($input.val()));
-		});
-
-		// current item
-		this.$cart_items.on('click', '.list-item', function() {
-			me.set_selected_item($(this));
-		});
-
-		this.wrapper.find('.additional_discount_percentage').on('change', (e) => {
-			const discount_percentage = flt(e.target.value,
-				precision("additional_discount_percentage"));
-
-			frappe.model.set_value(this.frm.doctype, this.frm.docname,
-				'additional_discount_percentage', discount_percentage)
-				.then(() => {
-					let discount_wrapper = this.wrapper.find('.discount_amount');
-					discount_wrapper.val(flt(this.frm.doc.discount_amount,
-						precision('discount_amount')));
-					discount_wrapper.trigger('change');
-				});
-		});
-
-		this.wrapper.find('.discount_amount').on('change', (e) => {
-			const discount_amount = flt(e.target.value, precision('discount_amount'));
-			frappe.model.set_value(this.frm.doctype, this.frm.docname,
-				'discount_amount', discount_amount);
-			this.frm.trigger('discount_amount')
-				.then(() => {
-					this.update_discount_fields();
-					this.update_taxes_and_totals();
-					this.update_grand_total();
-				});
-		});
-	}
-
-	update_discount_fields() {
-		let discount_wrapper = this.wrapper.find('.additional_discount_percentage');
-		let discount_amt_wrapper = this.wrapper.find('.discount_amount');
-		discount_wrapper.val(flt(this.frm.doc.additional_discount_percentage,
-			precision('additional_discount_percentage')));
-		discount_amt_wrapper.val(flt(this.frm.doc.discount_amount,
-			precision('discount_amount')));
-	}
-
-	set_selected_item($item) {
-		this.selected_item = $item;
-		this.$cart_items.find('.list-item').removeClass('current-item qty disc rate');
-		this.selected_item.addClass('current-item');
-		this.events.on_select_change();
-	}
-
-	unselect_all() {
-		this.$cart_items.find('.list-item').removeClass('current-item qty disc rate');
-		this.selected_item = null;
-		this.events.on_select_change();
-	}
-}
-
-class POSItems {
-	constructor({wrapper, frm, events}) {
-		this.wrapper = wrapper;
-		this.frm = frm;
-		this.items = {};
-		this.events = events;
-		this.currency = this.frm.doc.currency;
-
-		frappe.db.get_value("Item Group", {lft: 1, is_group: 1}, "name", (r) => {
-			this.parent_item_group = r.name;
-			this.make_dom();
-			this.make_fields();
-
-			this.init_clusterize();
-			this.bind_events();
-			this.load_items_data();
-		})
-	}
-
-	load_items_data() {
-		// bootstrap with 20 items
-		this.get_items()
-			.then(({ items }) => {
-				this.all_items = items;
-				this.items = items;
-				this.render_items(items);
-			});
-	}
-
-	reset_items() {
-		this.wrapper.find('.pos-items').empty();
-		this.init_clusterize();
-		this.load_items_data();
-	}
-
-	make_dom() {
-		this.wrapper.html(`
-			<div class="fields">
-				<div class="search-field">
-				</div>
-				<div class="item-group-field">
-				</div>
-			</div>
-			<div class="items-wrapper">
-			</div>
-		`);
-
-		this.items_wrapper = this.wrapper.find('.items-wrapper');
-		this.items_wrapper.append(`
-			<div class="list-item-table pos-items-wrapper">
-				<div class="pos-items image-view-container">
-				</div>
-			</div>
-		`);
-	}
-
-	make_fields() {
-		// Search field
-		const me = this;
-		this.search_field = frappe.ui.form.make_control({
-			df: {
-				fieldtype: 'Data',
-				label: __('Search Item (Ctrl + i)'),
-				placeholder: __('Search by item code, serial number, batch no or barcode')
-			},
-			parent: this.wrapper.find('.search-field'),
-			render_input: true,
-		});
-
-		frappe.ui.keys.on('ctrl+i', () => {
-			this.search_field.set_focus();
-		});
-
-		this.search_field.$input.on('input', (e) => {
-			clearTimeout(this.last_search);
-			this.last_search = setTimeout(() => {
-				const search_term = e.target.value;
-				const item_group = this.item_group_field ?
-					this.item_group_field.get_value() : '';
-
-				this.filter_items({ search_term:search_term,  item_group: item_group});
-			}, 300);
-		});
-
-		this.item_group_field = frappe.ui.form.make_control({
-			df: {
-				fieldtype: 'Link',
-				label: 'Item Group',
-				options: 'Item Group',
-				default: me.parent_item_group,
-				onchange: () => {
-					const item_group = this.item_group_field.get_value();
-					if (item_group) {
-						this.filter_items({ item_group: item_group });
-					}
-				},
-				get_query: () => {
-					return {
-						query: 'erpnext.selling.page.point_of_sale.point_of_sale.item_group_query',
-						filters: {
-							pos_profile: this.frm.doc.pos_profile
-						}
-					};
-				}
-			},
-			parent: this.wrapper.find('.item-group-field'),
-			render_input: true
-		});
-	}
-
-	init_clusterize() {
-		this.clusterize = new Clusterize({
-			scrollElem: this.wrapper.find('.pos-items-wrapper')[0],
-			contentElem: this.wrapper.find('.pos-items')[0],
-			rows_in_block: 6
-		});
-	}
-
-	render_items(items) {
-		let _items = items || this.items;
-
-		const all_items = Object.values(_items).map(item => this.get_item_html(item));
-		let row_items = [];
-
-		const row_container = '<div class="image-view-row">';
-		let curr_row = row_container;
-
-		for (let i=0; i < all_items.length; i++) {
-			// wrap 4 items in a div to emulate
-			// a row for clusterize
-			if(i % 4 === 0 && i !== 0) {
-				curr_row += '</div>';
-				row_items.push(curr_row);
-				curr_row = row_container;
-			}
-			curr_row += all_items[i];
-
-			if(i == all_items.length - 1) {
-				row_items.push(curr_row);
-			}
-		}
-
-		this.clusterize.update(row_items);
-	}
-
-	filter_items({ search_term='', item_group=this.parent_item_group }={}) {
-		if (search_term) {
-			search_term = search_term.toLowerCase();
-
-			// memoize
-			this.search_index = this.search_index || {};
-			if (this.search_index[search_term]) {
-				const items = this.search_index[search_term];
-				this.items = items;
-				this.render_items(items);
-				this.set_item_in_the_cart(items);
-				return;
-			}
-		} else if (item_group == this.parent_item_group) {
-			this.items = this.all_items;
-			return this.render_items(this.all_items);
-		}
-
-		this.get_items({search_value: search_term, item_group })
-			.then(({ items, serial_no, batch_no, barcode }) => {
-				if (search_term && !barcode) {
-					this.search_index[search_term] = items;
-				}
-
-				this.items = items;
-				this.render_items(items);
-				this.set_item_in_the_cart(items, serial_no, batch_no, barcode);
-			});
-	}
-
-	set_item_in_the_cart(items, serial_no, batch_no, barcode) {
-		if (serial_no) {
-			this.events.update_cart(items[0].item_code,
-				'serial_no', serial_no);
-			this.reset_search_field();
-			return;
-		}
-
-		if (batch_no) {
-			this.events.update_cart(items[0].item_code,
-				'batch_no', batch_no);
-			this.reset_search_field();
-			return;
-		}
-
-		if (items.length === 1 && (serial_no || batch_no || barcode)) {
-			this.events.update_cart(items[0].item_code,
-				'qty', '+1');
-			this.reset_search_field();
-		}
-	}
-
-	reset_search_field() {
-		this.search_field.set_value('');
-		this.search_field.$input.trigger("input");
-	}
-
-	bind_events() {
-		var me = this;
-		this.wrapper.on('click', '.pos-item-wrapper', function() {
-			const $item = $(this);
-			const item_code = unescape($item.attr('data-item-code'));
-			me.events.update_cart(item_code, 'qty', '+1');
-		});
-	}
-
-	get(item_code) {
-		let item = {};
-		this.items.map(data => {
-			if (data.item_code === item_code) {
-				item = data;
-			}
-		})
-
-		return item
-	}
-
-	get_all() {
-		return this.items;
-	}
-
-	get_item_html(item) {
-		const price_list_rate = format_currency(item.price_list_rate, this.currency);
-		const { item_code, item_name, item_image} = item;
-		const item_title = item_name || item_code;
-
-		const template = `
-			<div class="pos-item-wrapper image-view-item" data-item-code="${escape(item_code)}">
-				<div class="image-view-header">
-					<div>
-						<a class="grey list-id" data-name="${item_code}" title="${item_title}">
-							${item_title}
-						</a>
-					</div>
-				</div>
-				<div class="image-view-body">
-					<a	data-item-code="${item_code}"
-						title="${item_title}"
-					>
-						<div class="image-field"
-							style="${!item_image ? 'background-color: #fafbfc;' : ''} border: 0px;"
-						>
-							${!item_image ? `<span class="placeholder-text">
-									${frappe.get_abbr(item_title)}
-								</span>` : '' }
-							${item_image ? `<img src="${item_image}" alt="${item_title}">` : '' }
-						</div>
-						<span class="price-info">
-							${price_list_rate}
-						</span>
-					</a>
-				</div>
-			</div>
-		`;
-
-		return template;
-	}
-
-	get_items({start = 0, page_length = 40, search_value='', item_group=this.parent_item_group}={}) {
-		const price_list = this.frm.doc.selling_price_list;
-		return new Promise(res => {
-			frappe.call({
-				method: "erpnext.selling.page.point_of_sale.point_of_sale.get_items",
-				freeze: true,
-				args: {
-					start,
-					page_length,
-					price_list,
-					item_group,
-					search_value,
-					pos_profile: this.frm.doc.pos_profile
-				}
-			}).then(r => {
-				// const { items, serial_no, batch_no } = r.message;
-
-				// this.serial_no = serial_no || "";
-				res(r.message);
-			});
-		});
-	}
-}
-
-class NumberPad {
-	constructor({
-		wrapper, onclick, button_array,
-		add_class={}, disable_highlight=[],
-		reset_btns=[], del_btn='', disable_btns
-	}) {
-		this.wrapper = wrapper;
-		this.onclick = onclick;
-		this.button_array = button_array;
-		this.add_class = add_class;
-		this.disable_highlight = disable_highlight;
-		this.reset_btns = reset_btns;
-		this.del_btn = del_btn;
-		this.disable_btns = disable_btns || [];
-		this.make_dom();
-		this.bind_events();
-		this.value = '';
-	}
-
-	make_dom() {
-		if (!this.button_array) {
-			this.button_array = [
-				[1, 2, 3],
-				[4, 5, 6],
-				[7, 8, 9],
-				['', 0, '']
-			];
-		}
-
-		this.wrapper.html(`
-			<div class="number-pad">
-				${this.button_array.map(get_row).join("")}
-			</div>
-		`);
-
-		function get_row(row) {
-			return '<div class="num-row">' + row.map(get_col).join("") + '</div>';
-		}
-
-		function get_col(col) {
-			return `<div class="num-col" data-value="${col}"><div>${col}</div></div>`;
-		}
-
-		this.set_class();
-
-		if(this.disable_btns) {
-			this.disable_btns.forEach((btn) => {
-				const $btn = this.get_btn(btn);
-				$btn.prop("disabled", true)
-				$btn.hover(() => {
-					$btn.css('cursor','not-allowed');
-				})
-			})
-		}
-	}
-
-	enable_buttons(btns) {
-		btns.forEach((btn) => {
-			const $btn = this.get_btn(btn);
-			$btn.prop("disabled", false)
-			$btn.hover(() => {
-				$btn.css('cursor','pointer');
-			})
-		})
-	}
-
-	set_class() {
-		for (const btn in this.add_class) {
-			const class_name = this.add_class[btn];
-			this.get_btn(btn).addClass(class_name);
-		}
-	}
-
-	bind_events() {
-		// bind click event
-		const me = this;
-		this.wrapper.on('click', '.num-col', function() {
-			const $btn = $(this);
-			const btn_value = $btn.attr('data-value');
-			if (!me.disable_highlight.includes(btn_value)) {
-				me.highlight_button($btn);
-			}
-			if (me.reset_btns.includes(btn_value)) {
-				me.reset_value();
-			} else {
-				if (btn_value === me.del_btn) {
-					me.value = me.value.substr(0, me.value.length - 1);
-				} else {
-					me.value += btn_value;
-				}
-			}
-			me.onclick(btn_value);
-		});
-	}
-
-	reset_value() {
-		this.value = '';
-	}
-
-	get_value() {
-		return flt(this.value);
-	}
-
-	get_btn(btn_value) {
-		return this.wrapper.find(`.num-col[data-value="${btn_value}"]`);
-	}
-
-	highlight_button($btn) {
-		$btn.addClass('highlight');
-		setTimeout(() => $btn.removeClass('highlight'), 1000);
-	}
-
-	set_active(btn_value) {
-		const $btn = this.get_btn(btn_value);
-		this.wrapper.find('.num-col').removeClass('active');
-		$btn.addClass('active');
-	}
-
-	set_inactive() {
-		this.wrapper.find('.num-col').removeClass('active');
-	}
-}
-
-class Payment {
-	constructor({frm, events}) {
-		this.frm = frm;
-		this.events = events;
-		this.make();
-		this.bind_events();
-		this.set_primary_action();
-	}
-
-	open_modal() {
-		this.dialog.show();
-	}
-
-	make() {
-		this.set_flag();
-		this.dialog = new frappe.ui.Dialog({
-			fields: this.get_fields(),
-			width: 800,
-			invoice_frm: this.frm
-		});
-
-		this.set_title();
-
-		this.$body = this.dialog.body;
-
-		this.numpad = new NumberPad({
-			wrapper: $(this.$body).find('[data-fieldname="numpad"]'),
-			button_array: [
-				[1, 2, 3],
-				[4, 5, 6],
-				[7, 8, 9],
-				[__('Del'), 0, '.'],
-			],
-			onclick: () => {
-				if(this.fieldname) {
-					this.dialog.set_value(this.fieldname, this.numpad.get_value());
-				}
-			}
-		});
-	}
-
-	set_title() {
-		let title = __('Total Amount {0}',
-			[format_currency(this.frm.doc.rounded_total || this.frm.doc.grand_total,
-			this.frm.doc.currency)]);
-
-		this.dialog.set_title(title);
-	}
-
-	bind_events() {
-		var me = this;
-		$(this.dialog.body).find('.input-with-feedback').focusin(function() {
-			me.numpad.reset_value();
-			me.fieldname = $(this).prop('dataset').fieldname;
-			if (me.frm.doc.outstanding_amount > 0 &&
-				!in_list(['write_off_amount', 'change_amount'], me.fieldname)) {
-				me.frm.doc.payments.forEach((data) => {
-					if (data.mode_of_payment == me.fieldname && !data.amount) {
-						me.dialog.set_value(me.fieldname,
-							me.frm.doc.outstanding_amount / me.frm.doc.conversion_rate);
-						return;
-					}
-				})
-			}
-		});
-	}
-
-	set_primary_action() {
-		var me = this;
-
-		this.dialog.set_primary_action(__("Submit"), function() {
-			me.dialog.hide();
-			me.events.submit_form();
-		});
-	}
-
-	get_fields() {
-		const me = this;
-
-		let fields = this.frm.doc.payments.map(p => {
-			return {
-				fieldtype: 'Currency',
-				label: __(p.mode_of_payment),
-				options: me.frm.doc.currency,
-				fieldname: p.mode_of_payment,
-				default: p.amount,
-				onchange: () => {
-					const value = this.dialog.get_value(this.fieldname) || 0;
-					me.update_payment_value(this.fieldname, value);
-				}
-			};
-		});
-
-		fields = fields.concat([
-			{
-				fieldtype: 'Column Break',
-			},
-			{
-				fieldtype: 'HTML',
-				fieldname: 'numpad'
-			},
-			{
-				fieldtype: 'Section Break',
-				depends_on: 'eval: this.invoice_frm.doc.loyalty_program'
-			},
-			{
-				fieldtype: 'Check',
-				label: 'Redeem Loyalty Points',
-				fieldname: 'redeem_loyalty_points',
-				onchange: () => {
-					me.update_cur_frm_value("redeem_loyalty_points", () => {
-						frappe.flags.redeem_loyalty_points = false;
-						me.update_loyalty_points();
-					});
-				}
-			},
-			{
-				fieldtype: 'Column Break',
-			},
-			{
-				fieldtype: 'Int',
-				fieldname: "loyalty_points",
-				label: __("Loyalty Points"),
-				depends_on: "redeem_loyalty_points",
-				onchange: () => {
-					me.update_cur_frm_value("loyalty_points", () => {
-						frappe.flags.loyalty_points = false;
-						me.update_loyalty_points();
-					});
-				}
-			},
-			{
-				fieldtype: 'Currency',
-				label: __("Loyalty Amount"),
-				fieldname: "loyalty_amount",
-				options: me.frm.doc.currency,
-				read_only: 1,
-				depends_on: "redeem_loyalty_points"
-			},
-			{
-				fieldtype: 'Section Break',
-			},
-			{
-				fieldtype: 'Currency',
-				label: __("Write off Amount"),
-				options: me.frm.doc.currency,
-				fieldname: "write_off_amount",
-				default: me.frm.doc.write_off_amount,
-				onchange: () => {
-					me.update_cur_frm_value('write_off_amount', () => {
-						frappe.flags.change_amount = false;
-						me.update_change_amount();
-					});
-				}
-			},
-			{
-				fieldtype: 'Column Break',
-			},
-			{
-				fieldtype: 'Currency',
-				label: __("Change Amount"),
-				options: me.frm.doc.currency,
-				fieldname: "change_amount",
-				default: me.frm.doc.change_amount,
-				onchange: () => {
-					me.update_cur_frm_value('change_amount', () => {
-						frappe.flags.write_off_amount = false;
-						me.update_write_off_amount();
-					});
-				}
-			},
-			{
-				fieldtype: 'Section Break',
-			},
-			{
-				fieldtype: 'Currency',
-				label: __("Paid Amount"),
-				options: me.frm.doc.currency,
-				fieldname: "paid_amount",
-				default: me.frm.doc.paid_amount,
-				read_only: 1
-			},
-			{
-				fieldtype: 'Column Break',
-			},
-			{
-				fieldtype: 'Currency',
-				label: __("Outstanding Amount"),
-				options: me.frm.doc.currency,
-				fieldname: "outstanding_amount",
-				default: me.frm.doc.outstanding_amount,
-				read_only: 1
-			},
-		]);
-
-		return fields;
-	}
-
-	set_flag() {
-		frappe.flags.write_off_amount = true;
-		frappe.flags.change_amount = true;
-		frappe.flags.loyalty_points = true;
-		frappe.flags.redeem_loyalty_points = true;
-		frappe.flags.payment_method = true;
-	}
-
-	update_cur_frm_value(fieldname, callback) {
-		if (frappe.flags[fieldname]) {
-			const value = this.dialog.get_value(fieldname);
-			this.frm.set_value(fieldname, value)
-				.then(() => {
-					callback();
-				});
-		}
-
-		frappe.flags[fieldname] = true;
-	}
-
-	update_payment_value(fieldname, value) {
-		var me = this;
-			$.each(this.frm.doc.payments, function(i, data) {
-				if (__(data.mode_of_payment) == __(fieldname)) {
-					frappe.model.set_value('Sales Invoice Payment', data.name, 'amount', value)
-						.then(() => {
-							me.update_change_amount();
-							me.update_write_off_amount();
-						});
-				}
-			});
-	}
-
-	update_change_amount() {
-		this.dialog.set_value("change_amount", this.frm.doc.change_amount);
-		this.show_paid_amount();
-	}
-
-	update_write_off_amount() {
-		this.dialog.set_value("write_off_amount", this.frm.doc.write_off_amount);
-	}
-
-	show_paid_amount() {
-		this.dialog.set_value("paid_amount", this.frm.doc.paid_amount);
-		this.dialog.set_value("outstanding_amount", this.frm.doc.outstanding_amount);
-	}
-
-	update_payment_amount() {
-		var me = this;
-		$.each(this.frm.doc.payments, function(i, data) {
-			console.log("setting the ", data.mode_of_payment, " for the value", data.amount);
-			me.dialog.set_value(data.mode_of_payment, data.amount);
-		});
-	}
-
-	update_loyalty_points() {
-		if (this.dialog.get_value("redeem_loyalty_points")) {
-			this.dialog.set_value("loyalty_points", this.frm.doc.loyalty_points);
-			this.dialog.set_value("loyalty_amount", this.frm.doc.loyalty_amount);
-			this.update_payment_amount();
-			this.show_paid_amount();
-		}
-	}
-
-}
+	// online
+	wrapper.pos = new erpnext.PointOfSale.Controller(wrapper);
+	window.cur_pos = wrapper.pos;
+};
\ No newline at end of file
diff --git a/erpnext/selling/page/point_of_sale/point_of_sale.json b/erpnext/selling/page/point_of_sale/point_of_sale.json
index 6d2f5f2..99b86e4 100644
--- a/erpnext/selling/page/point_of_sale/point_of_sale.json
+++ b/erpnext/selling/page/point_of_sale/point_of_sale.json
@@ -1,33 +1,33 @@
 {
- "content": null, 
- "creation": "2017-08-07 17:08:56.737947", 
- "docstatus": 0, 
- "doctype": "Page", 
- "idx": 0, 
- "modified": "2017-09-11 13:49:05.415211", 
- "modified_by": "Administrator", 
- "module": "Selling", 
- "name": "point-of-sale", 
- "owner": "Administrator", 
- "page_name": "Point of Sale", 
- "restrict_to_domain": "Retail", 
+ "content": null,
+ "creation": "2020-01-28 22:05:44.819140",
+ "docstatus": 0,
+ "doctype": "Page",
+ "idx": 0,
+ "modified": "2020-06-01 15:41:06.348380",
+ "modified_by": "Administrator",
+ "module": "Selling",
+ "name": "point-of-sale",
+ "owner": "Administrator",
+ "page_name": "Point of Sale",
+ "restrict_to_domain": "Retail",
  "roles": [
   {
    "role": "Accounts User"
-  }, 
+  },
   {
    "role": "Accounts Manager"
-  }, 
+  },
   {
    "role": "Sales User"
-  }, 
+  },
   {
    "role": "Sales Manager"
   }
- ], 
- "script": null, 
- "standard": "Yes", 
- "style": null, 
- "system_page": 0, 
- "title": "Point of Sale"
+ ],
+ "script": null,
+ "standard": "Yes",
+ "style": null,
+ "system_page": 0,
+ "title": "Point Of Sale"
 }
\ No newline at end of file
diff --git a/erpnext/selling/page/point_of_sale/point_of_sale.py b/erpnext/selling/page/point_of_sale/point_of_sale.py
index dfa0f7f..f7b7ed8 100644
--- a/erpnext/selling/page/point_of_sale/point_of_sale.py
+++ b/erpnext/selling/page/point_of_sale/point_of_sale.py
@@ -6,6 +6,7 @@
 from frappe.utils.nestedset import get_root_of
 from frappe.utils import cint
 from erpnext.accounts.doctype.pos_profile.pos_profile import get_item_groups
+from erpnext.accounts.doctype.pos_invoice.pos_invoice import get_stock_availability
 
 from six import string_types
 
@@ -43,6 +44,7 @@
 		SELECT
 			name AS item_code,
 			item_name,
+			description,
 			stock_uom,
 			image AS item_image,
 			idx AS idx,
@@ -53,10 +55,11 @@
 			disabled = 0
 				AND has_variants = 0
 				AND is_sales_item = 1
+				AND is_fixed_asset = 0
 				AND item_group in (SELECT name FROM `tabItem Group` WHERE lft >= {lft} AND rgt <= {rgt})
 				AND {condition}
 		ORDER BY
-			idx desc
+			name asc
 		LIMIT
 			{start}, {page_length}"""
 		.format(
@@ -73,32 +76,14 @@
 			fields = ["item_code", "price_list_rate", "currency"],
 			filters = {'price_list': price_list, 'item_code': ['in', items]})
 
-		item_prices, bin_data = {}, {}
+		item_prices = {}
 		for d in item_prices_data:
 			item_prices[d.item_code] = d
 
-		# prepare filter for bin query
-		bin_filters = {'item_code': ['in', items]}
-		if warehouse:
-			bin_filters['warehouse'] = warehouse
-		if display_items_in_stock:
-			bin_filters['actual_qty'] = [">", 0]
-
-		# query item bin
-		bin_data = frappe.get_all(
-			'Bin', fields=['item_code', 'sum(actual_qty) as actual_qty'],
-			filters=bin_filters, group_by='item_code'
-		)
-
-		# convert list of dict into dict as {item_code: actual_qty}
-		bin_dict = {}
-		for b in bin_data:
-			bin_dict[b.get('item_code')] = b.get('actual_qty')
-
 		for item in items_data:
 			item_code = item.item_code
 			item_price = item_prices.get(item_code) or {}
-			item_stock_qty = bin_dict.get(item_code)
+			item_stock_qty = get_stock_availability(item_code, warehouse)
 
 			if display_items_in_stock and not item_stock_qty:
 				pass
@@ -116,6 +101,13 @@
 		'items': result
 	}
 
+	if len(res['items']) == 1:
+		res['items'][0].setdefault('serial_no', serial_no)
+		res['items'][0].setdefault('batch_no', batch_no)
+		res['items'][0].setdefault('barcode', barcode)
+
+		return res
+
 	if serial_no:
 		res.update({
 			'serial_no': serial_no
@@ -167,6 +159,7 @@
 
 	return cond % tuple(item_groups)
 
+@frappe.whitelist()
 def item_group_query(doctype, txt, searchfield, start, page_len, filters):
 	item_groups = []
 	cond = "1=1"
@@ -185,6 +178,73 @@
 			{'txt': '%%%s%%' % txt})
 
 @frappe.whitelist()
-def get_pos_fields():
-	return frappe.get_all("POS Field", fields=["label", "fieldname",
-		"fieldtype", "default_value", "reqd", "read_only", "options"])
\ No newline at end of file
+def check_opening_entry(user):
+	open_vouchers = frappe.db.get_all("POS Opening Entry", 
+		filters = { 
+			"user": user, 
+			"pos_closing_entry": ["in", ["", None]],
+			"docstatus": 1
+		}, 
+		fields = ["name", "company", "pos_profile", "period_start_date"],
+		order_by = "period_start_date desc"
+	)
+
+	return open_vouchers
+
+@frappe.whitelist()
+def create_opening_voucher(pos_profile, company, balance_details):
+	import json
+	balance_details = json.loads(balance_details)
+
+	new_pos_opening = frappe.get_doc({
+		'doctype': 'POS Opening Entry',
+		"period_start_date": frappe.utils.get_datetime(),
+		"posting_date": frappe.utils.getdate(),
+		"user": frappe.session.user,
+		"pos_profile": pos_profile,
+		"company": company,
+	})
+	new_pos_opening.set("balance_details", balance_details)
+	new_pos_opening.submit()
+
+	return new_pos_opening.as_dict()
+
+@frappe.whitelist()
+def get_past_order_list(search_term, status, limit=20):
+	fields = ['name', 'grand_total', 'currency', 'customer', 'posting_time', 'posting_date']
+	invoice_list = []
+
+	if search_term and status:
+		invoices_by_customer = frappe.db.get_all('POS Invoice', filters={
+			'customer': ['like', '%{}%'.format(search_term)],
+			'status': status
+		}, fields=fields)
+		invoices_by_name = frappe.db.get_all('POS Invoice', filters={
+			'name': ['like', '%{}%'.format(search_term)],
+			'status': status
+		}, fields=fields)
+
+		invoice_list = invoices_by_customer + invoices_by_name
+	elif status:
+		invoice_list = frappe.db.get_all('POS Invoice', filters={
+			'status': status
+		}, fields=fields)
+	
+	return invoice_list
+
+@frappe.whitelist()
+def set_customer_info(fieldname, customer, value=""):
+	if fieldname == 'loyalty_program':
+		frappe.db.set_value('Customer', customer, 'loyalty_program', value)
+
+	contact = frappe.get_cached_value('Customer', customer, 'customer_primary_contact')
+
+	if contact:
+		contact_doc = frappe.get_doc('Contact', contact)
+		if fieldname == 'email_id':
+			contact_doc.set('email_ids', [{ 'email_id': value, 'is_primary': 1}])
+			frappe.db.set_value('Customer', customer, 'email_id', value)
+		elif fieldname == 'mobile_no': 
+			contact_doc.set('phone_nos', [{ 'phone': value, 'is_primary_mobile_no': 1}])
+			frappe.db.set_value('Customer', customer, 'mobile_no', value)
+		contact_doc.save()
\ No newline at end of file
diff --git a/erpnext/selling/page/point_of_sale/pos_controller.js b/erpnext/selling/page/point_of_sale/pos_controller.js
new file mode 100644
index 0000000..483ef78
--- /dev/null
+++ b/erpnext/selling/page/point_of_sale/pos_controller.js
@@ -0,0 +1,714 @@
+{% include "erpnext/selling/page/point_of_sale/onscan.js" %}
+{% include "erpnext/selling/page/point_of_sale/pos_item_selector.js" %}
+{% include "erpnext/selling/page/point_of_sale/pos_item_cart.js" %}
+{% include "erpnext/selling/page/point_of_sale/pos_item_details.js" %}
+{% include "erpnext/selling/page/point_of_sale/pos_payment.js" %}
+{% include "erpnext/selling/page/point_of_sale/pos_number_pad.js" %}
+{% include "erpnext/selling/page/point_of_sale/pos_past_order_list.js" %}
+{% include "erpnext/selling/page/point_of_sale/pos_past_order_summary.js" %}
+
+erpnext.PointOfSale.Controller = class {
+    constructor(wrapper) {
+		this.wrapper = $(wrapper).find('.layout-main-section');
+		this.page = wrapper.page;
+
+		this.load_assets();
+	}
+
+	load_assets() {
+		// after loading assets first check if opening entry has been made
+		frappe.require(['assets/erpnext/css/pos.css'], this.check_opening_entry.bind(this));
+	}
+
+	check_opening_entry() {
+		return frappe.call("erpnext.selling.page.point_of_sale.point_of_sale.check_opening_entry", { "user": frappe.session.user })
+			.then((r) => {
+				if (r.message.length) {
+					// assuming only one opening voucher is available for the current user
+					this.prepare_app_defaults(r.message[0]);
+				} else {
+					this.create_opening_voucher();
+				}
+			});
+	}
+
+	create_opening_voucher() {
+		const table_fields = [
+			{ fieldname: "mode_of_payment", fieldtype: "Link", in_list_view: 1, label: "Mode of Payment", options: "Mode of Payment", reqd: 1 },
+			{ fieldname: "opening_amount", fieldtype: "Currency", in_list_view: 1, label: "Opening Amount", options: "company:company_currency", reqd: 1 }
+		];
+
+		const dialog = new frappe.ui.Dialog({
+			title: __('Create POS Opening Entry'),
+			fields: [
+				{
+					fieldtype: 'Link', label: __('Company'), default: frappe.defaults.get_default('company'),
+					options: 'Company', fieldname: 'company', reqd: 1
+				},
+				{
+					fieldtype: 'Link', label: __('POS Profile'),
+					options: 'POS Profile', fieldname: 'pos_profile', reqd: 1,
+					onchange: () => {
+						const pos_profile = dialog.fields_dict.pos_profile.get_value();
+						const company = dialog.fields_dict.company.get_value();
+						const user = frappe.session.user
+
+						if (!pos_profile || !company || !user) return;
+
+						// auto fetch last closing entry's balance details
+						frappe.db.get_list("POS Closing Entry", {
+							filters: { company, pos_profile, user },
+							limit: 1,
+							order_by: 'period_end_date desc'
+						}).then((res) => {
+							if (!res.length) return;
+							const pos_closing_entry = res[0];
+							frappe.db.get_doc("POS Closing Entry", pos_closing_entry.name).then(({ payment_reconciliation }) => {
+								dialog.fields_dict.balance_details.df.data = [];
+								payment_reconciliation.forEach(pay => {
+									const { mode_of_payment, closing_amount } = pay;
+									dialog.fields_dict.balance_details.df.data.push({
+										mode_of_payment: mode_of_payment
+									});
+								});
+								dialog.fields_dict.balance_details.grid.refresh();
+							});
+						});
+					}
+				},
+				{
+					fieldname: "balance_details",
+					fieldtype: "Table",
+					label: "Opening Balance Details",
+					cannot_add_rows: false,
+					in_place_edit: true,
+					reqd: 1,
+					data: [],
+					fields: table_fields
+				}
+			],
+			primary_action: ({ company, pos_profile, balance_details }) => {
+				if (!balance_details.length) {
+					frappe.show_alert({
+						message: __("Please add Mode of payments and opening balance details."),
+						indicator: 'red'
+					})
+					frappe.utils.play_sound("error");
+					return;
+				}
+				frappe.dom.freeze();
+				return frappe.call("erpnext.selling.page.point_of_sale.point_of_sale.create_opening_voucher", 
+					{ pos_profile, company, balance_details })
+					.then((r) => {
+						frappe.dom.unfreeze();
+						dialog.hide();
+						if (r.message) {
+							this.prepare_app_defaults(r.message);
+						}
+					})
+			},
+			primary_action_label: __('Submit')
+		});
+		dialog.show();
+	}
+
+	prepare_app_defaults(data) {
+		this.pos_opening = data.name;
+		this.company = data.company;
+		this.pos_profile = data.pos_profile;
+		this.pos_opening_time = data.period_start_date;
+
+		frappe.db.get_value('Stock Settings', undefined, 'allow_negative_stock').then(({ message }) => {
+			this.allow_negative_stock = flt(message.allow_negative_stock) || false;
+		});
+
+		frappe.db.get_doc("POS Profile", this.pos_profile).then((profile) => {
+			this.customer_groups = profile.customer_groups.map(group => group.customer_group);
+			this.cart.make_customer_selector();
+		});
+
+		this.item_stock_map = {};
+
+		this.make_app();
+	}
+
+	set_opening_entry_status() {
+		this.page.set_title_sub(
+			`<span class="indicator orange">
+				<a class="text-muted" href="#Form/POS%20Opening%20Entry/${this.pos_opening}">
+					Opened at ${moment(this.pos_opening_time).format("Do MMMM, h:mma")}
+				</a>
+			</span>`);
+	}
+
+	make_app() {
+		return frappe.run_serially([
+			() => frappe.dom.freeze(),
+			() => {
+				this.set_opening_entry_status();
+				this.prepare_dom();
+				this.prepare_components();
+				this.prepare_menu();
+			},
+			() => this.make_new_invoice(),
+			() => frappe.dom.unfreeze(),
+			() => this.page.set_title(__('Point of Sale Beta')),
+		]);
+	}
+
+	prepare_dom() {
+		this.wrapper.append(`
+			<div class="app grid grid-cols-10 pt-8 gap-6"></div>`
+		);
+
+		this.$components_wrapper = this.wrapper.find('.app');
+	}
+
+	prepare_components() {
+		this.init_item_selector();
+		this.init_item_details();
+		this.init_item_cart();
+		this.init_payments();
+		this.init_recent_order_list();
+		this.init_order_summary();
+	}
+
+	prepare_menu() {
+		var me = this;
+		this.page.clear_menu();
+
+		this.page.add_menu_item(__("Form View"), function () {
+			frappe.model.sync(me.frm.doc);
+			frappe.set_route("Form", me.frm.doc.doctype, me.frm.doc.name);
+		});
+
+		this.page.add_menu_item(__("Toggle Recent Orders"), () => {
+			const show = this.recent_order_list.$component.hasClass('d-none');
+			this.toggle_recent_order_list(show);
+		});
+
+		this.page.add_menu_item(__("Save as Draft"), this.save_draft_invoice.bind(this));
+
+		frappe.ui.keys.on("ctrl+s", this.save_draft_invoice.bind(this));
+
+		this.page.add_menu_item(__('Close the POS'), this.close_pos.bind(this));
+
+		frappe.ui.keys.on("shift+ctrl+s", this.close_pos.bind(this));
+	}
+
+	save_draft_invoice() {
+		if (!this.$components_wrapper.is(":visible")) return;
+
+		if (this.frm.doc.items.length == 0) {
+			frappe.show_alert({
+				message:__("You must add atleast one item to save it as draft."), 
+				indicator:'red'
+			});
+			frappe.utils.play_sound("error");
+			return;
+		}
+
+		this.frm.save(undefined, undefined, undefined, () => {
+			frappe.show_alert({
+				message:__("There was an error saving the document."), 
+				indicator:'red'
+			});
+			frappe.utils.play_sound("error");
+		}).then(() => {
+			frappe.run_serially([
+				() => frappe.dom.freeze(),
+				() => this.make_new_invoice(),
+				() => frappe.dom.unfreeze(),
+			]);
+		})
+	}
+
+	close_pos() {
+		if (!this.$components_wrapper.is(":visible")) return;
+
+		let voucher = frappe.model.get_new_doc('POS Closing Entry');
+		voucher.pos_profile = this.frm.doc.pos_profile;
+		voucher.user = frappe.session.user;
+		voucher.company = this.frm.doc.company;
+		voucher.pos_opening_entry = this.pos_opening;
+		voucher.period_end_date = frappe.datetime.now_datetime();
+		voucher.posting_date = frappe.datetime.now_date();
+		frappe.set_route('Form', 'POS Closing Entry', voucher.name);
+	}
+
+	init_item_selector() {
+		this.item_selector = new erpnext.PointOfSale.ItemSelector({
+			wrapper: this.$components_wrapper,
+			pos_profile: this.pos_profile,
+			events: {
+				item_selected: args => this.on_cart_update(args),
+
+				get_frm: () => this.frm || {},
+
+				get_allowed_item_group: () => this.item_groups
+			}
+		})
+	}
+
+	init_item_cart() {
+		this.cart = new erpnext.PointOfSale.ItemCart({
+			wrapper: this.$components_wrapper,
+			events: {
+				get_frm: () => this.frm,
+
+				cart_item_clicked: (item_code, batch_no, uom) => {
+					const item_row = this.frm.doc.items.find(
+						i => i.item_code === item_code 
+							&& i.uom === uom
+							&& (!batch_no || (batch_no && i.batch_no === batch_no))
+					);
+					this.item_details.toggle_item_details_section(item_row);
+				},
+
+				numpad_event: (value, action) => this.update_item_field(value, action),
+
+				checkout: () => this.payment.checkout(),
+
+				edit_cart: () => this.payment.edit_cart(),
+
+				customer_details_updated: (details) => {
+					this.customer_details = details;
+					// will add/remove LP payment method
+					this.payment.render_loyalty_points_payment_mode();
+				},
+
+				get_allowed_customer_group: () => this.customer_groups
+			}
+		})
+	}
+
+	init_item_details() {
+		this.item_details = new erpnext.PointOfSale.ItemDetails({
+			wrapper: this.$components_wrapper,
+			events: {
+				get_frm: () => this.frm,
+
+				toggle_item_selector: (minimize) => {
+					this.item_selector.resize_selector(minimize);
+					this.cart.toggle_numpad(minimize);
+				},
+
+				form_updated: async (cdt, cdn, fieldname, value) => {
+					const item_row = frappe.model.get_doc(cdt, cdn);
+					if (item_row && item_row[fieldname] != value) {
+
+						if (fieldname === 'qty' && flt(value) == 0) {
+							this.remove_item_from_cart();
+							return;
+						}
+
+						const { item_code, batch_no, uom } = this.item_details.current_item;
+						const event = {
+							field: fieldname,
+							value,
+							item: { item_code, batch_no, uom }
+						}
+						return this.on_cart_update(event)
+					}
+				},
+
+				item_field_focused: (fieldname) => {
+					this.cart.toggle_numpad_field_edit(fieldname);
+				},
+				set_value_in_current_cart_item: (selector, value) => {
+					this.cart.update_selector_value_in_cart_item(selector, value, this.item_details.current_item);
+				},
+				clone_new_batch_item_in_frm: (batch_serial_map, current_item) => {
+					// called if serial nos are 'auto_selected' and if those serial nos belongs to multiple batches
+					// for each unique batch new item row is added in the form & cart
+					Object.keys(batch_serial_map).forEach(batch => {
+						const { item_code, batch_no } = current_item;
+						const item_to_clone = this.frm.doc.items.find(i => i.item_code === item_code && i.batch_no === batch_no);
+						const new_row = this.frm.add_child("items", { ...item_to_clone });
+						// update new serialno and batch
+						new_row.batch_no = batch;
+						new_row.serial_no = batch_serial_map[batch].join(`\n`);
+						new_row.qty = batch_serial_map[batch].length;
+						this.frm.doc.items.forEach(row => {
+							if (item_code === row.item_code) {
+								this.update_cart_html(row);
+							}
+						});
+					})
+				},
+				remove_item_from_cart: () => this.remove_item_from_cart(),
+				get_item_stock_map: () => this.item_stock_map,
+				close_item_details: () => {
+					this.item_details.toggle_item_details_section(undefined);
+					this.cart.prev_action = undefined;
+					this.cart.toggle_item_highlight();
+				},
+				get_available_stock: (item_code, warehouse) => this.get_available_stock(item_code, warehouse)
+			}
+		});
+	}
+
+	init_payments() {
+		this.payment = new erpnext.PointOfSale.Payment({
+			wrapper: this.$components_wrapper,
+			events: {
+				get_frm: () => this.frm || {},
+
+				get_customer_details: () => this.customer_details || {},
+
+				toggle_other_sections: (show) => {
+					if (show) {
+						this.item_details.$component.hasClass('d-none') ? '' : this.item_details.$component.addClass('d-none');
+						this.item_selector.$component.addClass('d-none');
+					} else {
+						this.item_selector.$component.removeClass('d-none');
+					}
+				},
+
+				submit_invoice: () => {
+					this.frm.savesubmit()
+						.then((r) => {
+							// this.set_invoice_status();
+							this.toggle_components(false);
+							this.order_summary.toggle_component(true);
+							this.order_summary.load_summary_of(this.frm.doc, true);
+							frappe.show_alert({
+								indicator: 'green',
+								message: __(`POS invoice ${r.doc.name} created succesfully`)
+							});
+						});
+				}
+			}
+		});
+	}
+
+	init_recent_order_list() {
+		this.recent_order_list = new erpnext.PointOfSale.PastOrderList({
+			wrapper: this.$components_wrapper,
+			events: {
+				open_invoice_data: (name) => {
+					frappe.db.get_doc('POS Invoice', name).then((doc) => {
+						this.order_summary.load_summary_of(doc);
+					});
+				},
+				reset_summary: () => this.order_summary.show_summary_placeholder()
+			}
+		})
+	}
+
+	init_order_summary() {
+		this.order_summary = new erpnext.PointOfSale.PastOrderSummary({
+			wrapper: this.$components_wrapper,
+			events: {
+				get_frm: () => this.frm,
+
+				process_return: (name) => {
+					this.recent_order_list.toggle_component(false);
+					frappe.db.get_doc('POS Invoice', name).then((doc) => {
+						frappe.run_serially([
+							() => this.make_return_invoice(doc),
+							() => this.cart.load_invoice(),
+							() => this.item_selector.toggle_component(true)
+						]);
+					});
+				},
+				edit_order: (name) => {
+					this.recent_order_list.toggle_component(false);
+					frappe.run_serially([
+						() => this.frm.refresh(name),
+						() => this.cart.load_invoice(),
+						() => this.item_selector.toggle_component(true)
+					]);
+				},
+				new_order: () => {
+					frappe.run_serially([
+						() => frappe.dom.freeze(),
+						() => this.make_new_invoice(),
+						() => this.item_selector.toggle_component(true),
+						() => frappe.dom.unfreeze(),
+					]);
+				}
+			}
+		})
+	}
+
+	
+
+	toggle_recent_order_list(show) {
+		this.toggle_components(!show);
+		this.recent_order_list.toggle_component(show);
+		this.order_summary.toggle_component(show);
+	}
+
+	toggle_components(show) {
+		this.cart.toggle_component(show);
+		this.item_selector.toggle_component(show);
+
+		// do not show item details or payment if recent order is toggled off
+		!show ? (this.item_details.toggle_component(false) || this.payment.toggle_component(false)) : '';
+	}
+
+	make_new_invoice() {
+		return frappe.run_serially([
+			() => this.make_sales_invoice_frm(),
+			() => this.set_pos_profile_data(),
+			() => this.set_pos_profile_status(),
+			() => this.cart.load_invoice(),
+		]);
+	}
+
+	make_sales_invoice_frm() {
+		const doctype = 'POS Invoice';
+		return new Promise(resolve => {
+			if (this.frm) {
+				this.frm = this.get_new_frm(this.frm);
+				this.frm.doc.items = [];
+				this.frm.doc.is_pos = 1
+				resolve();
+			} else {
+				frappe.model.with_doctype(doctype, () => {
+					this.frm = this.get_new_frm();
+					this.frm.doc.items = [];
+					this.frm.doc.is_pos = 1
+					resolve();
+				});
+			}
+		});
+	}
+
+	get_new_frm(_frm) {
+		const doctype = 'POS Invoice';
+		const page = $('<div>');
+		const frm = _frm || new frappe.ui.form.Form(doctype, page, false);
+		const name = frappe.model.make_new_doc_and_get_name(doctype, true);
+		frm.refresh(name);
+
+		return frm;
+	}
+
+	async make_return_invoice(doc) {
+		frappe.dom.freeze();
+		this.frm = this.get_new_frm(this.frm);
+		this.frm.doc.items = [];
+		const res = await frappe.call({
+			method: "erpnext.accounts.doctype.pos_invoice.pos_invoice.make_sales_return",
+			args: {
+				'source_name': doc.name,
+				'target_doc': this.frm.doc
+			}
+		});
+		frappe.model.sync(res.message);
+		await this.set_pos_profile_data();
+		frappe.dom.unfreeze();
+	}
+
+	set_pos_profile_data() {
+		if (this.company && !this.frm.doc.company) this.frm.doc.company = this.company;
+		if (this.pos_profile && !this.frm.doc.pos_profile) this.frm.doc.pos_profile = this.pos_profile;
+		if (!this.frm.doc.company) return;
+
+		return new Promise(resolve => {
+			return this.frm.call({
+				doc: this.frm.doc,
+				method: "set_missing_values",
+			}).then((r) => {
+				if(!r.exc) {
+					if (!this.frm.doc.pos_profile) {
+						frappe.dom.unfreeze();
+						this.raise_exception_for_pos_profile();
+					}
+					this.frm.trigger("update_stock");
+					this.frm.trigger('calculate_taxes_and_totals');
+					if(this.frm.doc.taxes_and_charges) this.frm.script_manager.trigger("taxes_and_charges");
+					frappe.model.set_default_values(this.frm.doc);
+					if (r.message) {
+						this.frm.pos_print_format = r.message.print_format || "";
+						this.frm.meta.default_print_format = r.message.print_format || "";
+						this.frm.allow_edit_rate = r.message.allow_edit_rate;
+						this.frm.allow_edit_discount = r.message.allow_edit_discount;
+						this.frm.doc.campaign = r.message.campaign;
+					}
+				}
+				resolve();
+			});
+		});
+	}
+
+	raise_exception_for_pos_profile() {
+		setTimeout(() => frappe.set_route('List', 'POS Profile'), 2000);
+		frappe.throw(__("POS Profile is required to use Point-of-Sale"));
+	}
+
+	set_invoice_status() {
+		const [status, indicator] = frappe.listview_settings["POS Invoice"].get_indicator(this.frm.doc);
+		this.page.set_indicator(__(`${status}`), indicator);
+	}
+
+	set_pos_profile_status() {
+		this.page.set_indicator(__(`${this.pos_profile}`), "blue");
+	}
+
+	async on_cart_update(args) {
+		frappe.dom.freeze();
+		try {
+			let { field, value, item } = args;
+			const { item_code, batch_no, serial_no, uom } = item;
+			let item_row = this.get_item_from_frm(item_code, batch_no, uom);
+
+			const item_selected_from_selector = field === 'qty' && value === "+1"
+
+			if (item_row) {
+				item_selected_from_selector && (value = item_row.qty + flt(value))
+
+				field === 'qty' && (value = flt(value));
+
+				if (field === 'qty' && value > 0 && !this.allow_negative_stock)
+					await this.check_stock_availability(item_row, value, this.frm.doc.set_warehouse);
+				
+				if (this.is_current_item_being_edited(item_row) || item_selected_from_selector) {
+					await frappe.model.set_value(item_row.doctype, item_row.name, field, value);
+					this.update_cart_html(item_row);
+				}
+
+			} else {
+				if (!this.frm.doc.customer) {
+					frappe.dom.unfreeze();
+					frappe.show_alert({
+						message: __('You must select a customer before adding an item.'),
+						indicator: 'orange'
+					});
+					frappe.utils.play_sound("error");
+					return;
+				}
+				item_selected_from_selector && (value = flt(value))
+
+				const args = { item_code, batch_no, [field]: value };
+
+				if (serial_no) args['serial_no'] = serial_no;
+
+				if (field === 'serial_no') args['qty'] = value.split(`\n`).length || 0;
+
+				item_row = this.frm.add_child('items', args);
+
+				if (field === 'qty' && value !== 0 && !this.allow_negative_stock)
+					await this.check_stock_availability(item_row, value, this.frm.doc.set_warehouse);
+
+				await this.trigger_new_item_events(item_row);
+
+				this.check_serial_batch_selection_needed(item_row) && this.edit_item_details_of(item_row);
+				this.update_cart_html(item_row);
+			}	
+		} catch (error) {
+			console.log(error);
+		} finally {
+			frappe.dom.unfreeze();
+		}
+	}
+
+	get_item_from_frm(item_code, batch_no, uom) {
+		const has_batch_no = batch_no;
+		return this.frm.doc.items.find(
+			i => i.item_code === item_code 
+				&& (!has_batch_no || (has_batch_no && i.batch_no === batch_no))
+				&& (i.uom === uom)
+		);
+	}
+
+	edit_item_details_of(item_row) {
+		this.item_details.toggle_item_details_section(item_row);
+	}
+
+	is_current_item_being_edited(item_row) {
+		const { item_code, batch_no } = this.item_details.current_item;
+
+		return item_code !== item_row.item_code || batch_no != item_row.batch_no ? false : true;
+	}
+
+	update_cart_html(item_row, remove_item) {
+		this.cart.update_item_html(item_row, remove_item);
+		this.cart.update_totals_section(this.frm);
+	}
+
+	check_serial_batch_selection_needed(item_row) {
+		// right now item details is shown for every type of item.
+		// if item details is not shown for every item then this fn will be needed
+		const serialized = item_row.has_serial_no;
+		const batched = item_row.has_batch_no;
+		const no_serial_selected = !item_row.serial_no;
+		const no_batch_selected = !item_row.batch_no;
+
+		if ((serialized && no_serial_selected) || (batched && no_batch_selected) || 
+			(serialized && batched && (no_batch_selected || no_serial_selected))) {
+			return true;
+		}
+		return false;
+	}
+
+	async trigger_new_item_events(item_row) {
+		await this.frm.script_manager.trigger('item_code', item_row.doctype, item_row.name)
+		await this.frm.script_manager.trigger('qty', item_row.doctype, item_row.name)
+	}
+
+	async check_stock_availability(item_row, qty_needed, warehouse) {
+		const available_qty = (await this.get_available_stock(item_row.item_code, warehouse)).message;
+
+		frappe.dom.unfreeze();
+		if (!(available_qty > 0)) {
+			frappe.model.clear_doc(item_row.doctype, item_row.name);
+			frappe.throw(__(`Item Code: ${item_row.item_code.bold()} is not available under warehouse ${warehouse.bold()}.`))
+		} else if (available_qty < qty_needed) {
+			frappe.show_alert({
+				message: __(`Stock quantity not enough for Item Code: ${item_row.item_code.bold()} under warehouse ${warehouse.bold()}. 
+					Available quantity ${available_qty.toString().bold()}.`),
+				indicator: 'orange'
+			});
+			frappe.utils.play_sound("error");
+			this.item_details.qty_control.set_value(flt(available_qty));
+		}
+		frappe.dom.freeze();
+	}
+
+	get_available_stock(item_code, warehouse) {
+		const me = this;
+		return frappe.call({
+			method: "erpnext.accounts.doctype.pos_invoice.pos_invoice.get_stock_availability",
+			args: {
+				'item_code': item_code,
+				'warehouse': warehouse,
+			},
+			callback(res) {
+				if (!me.item_stock_map[item_code])
+					me.item_stock_map[item_code] = {}
+				me.item_stock_map[item_code][warehouse] = res.message;
+			}
+		});
+	}
+
+	update_item_field(value, field_or_action) {
+		if (field_or_action === 'checkout') {
+			this.item_details.toggle_item_details_section(undefined);
+		} else if (field_or_action === 'remove') {
+			this.remove_item_from_cart();
+		} else {
+			const field_control = this.item_details[`${field_or_action}_control`];
+			if (!field_control) return;
+			field_control.set_focus();
+			value != "" && field_control.set_value(value);
+		}
+	}
+
+	remove_item_from_cart() {
+		frappe.dom.freeze();
+		const { doctype, name, current_item } = this.item_details;
+
+		frappe.model.set_value(doctype, name, 'qty', 0);
+
+		this.frm.script_manager.trigger('qty', doctype, name).then(() => {
+			frappe.model.clear_doc(doctype, name);
+			this.update_cart_html(current_item, true);
+			this.item_details.toggle_item_details_section(undefined);
+			frappe.dom.unfreeze();
+		})
+	}
+}
+
diff --git a/erpnext/selling/page/point_of_sale/pos_item_cart.js b/erpnext/selling/page/point_of_sale/pos_item_cart.js
new file mode 100644
index 0000000..c23a6ad
--- /dev/null
+++ b/erpnext/selling/page/point_of_sale/pos_item_cart.js
@@ -0,0 +1,951 @@
+erpnext.PointOfSale.ItemCart = class {
+    constructor({ wrapper, events }) {
+		this.wrapper = wrapper;
+		this.events = events;
+        this.customer_info = undefined;
+        
+        this.init_component();
+    }
+    
+    init_component() {
+        this.prepare_dom();
+        this.init_child_components();
+		this.bind_events();
+		this.attach_shortcuts();
+    }
+
+    prepare_dom() {
+		this.wrapper.append(
+            `<section class="col-span-4 flex flex-col shadow rounded item-cart bg-white mx-h-70 h-100"></section>`
+        )
+
+        this.$component = this.wrapper.find('.item-cart');
+    }
+
+    init_child_components() {
+        this.init_customer_selector();
+        this.init_cart_components();
+    }
+
+    init_customer_selector() {
+		this.$component.append(
+            `<div class="customer-section rounded flex flex-col m-8 mb-0"></div>`
+        )
+		this.$customer_section = this.$component.find('.customer-section');
+	}
+	
+	reset_customer_selector() {
+		const frm = this.events.get_frm();
+		frm.set_value('customer', '');
+		this.$customer_section.removeClass('border pr-4 pl-4');
+		this.make_customer_selector();
+		this.customer_field.set_focus();
+	}
+    
+    init_cart_components() {
+        this.$component.append(
+			`<div class="cart-container flex flex-col items-center rounded flex-1 relative">
+				<div class="absolute flex flex-col p-8 pt-0 w-full h-full">
+					<div class="flex text-grey cart-header pt-2 pb-2 p-4 mt-2 mb-2 w-full f-shrink-0">
+						<div class="flex-1">Item</div>
+						<div class="mr-4">Qty</div>
+						<div class="rate-list-header mr-1 text-right">Amount</div>
+					</div>
+					<div class="cart-items-section flex flex-col flex-1 scroll-y rounded w-full"></div>
+					<div class="cart-totals-section flex flex-col w-full mt-4 f-shrink-0"></div>
+					<div class="numpad-section flex flex-col mt-4 d-none w-full p-8 pt-0 pb-0 f-shrink-0"></div>
+				</div>		
+            </div>`
+        );
+		this.$cart_container = this.$component.find('.cart-container');
+
+		this.make_cart_totals_section();
+		this.make_cart_items_section();
+        this.make_cart_numpad();
+    }
+
+    make_cart_items_section() {
+        this.$cart_header = this.$component.find('.cart-header');
+        this.$cart_items_wrapper = this.$component.find('.cart-items-section');
+
+		this.make_no_items_placeholder();
+    }
+    
+    make_no_items_placeholder() {
+		this.$cart_header.addClass('d-none');
+		this.$cart_items_wrapper.html(
+			`<div class="no-item-wrapper flex items-center h-18">
+				<div class="flex-1 text-center text-grey">No items in cart</div>
+			</div>`
+		)
+		this.$cart_items_wrapper.addClass('mt-4 border-grey border-dashed');
+	}
+
+    make_cart_totals_section() {
+        this.$totals_section = this.$component.find('.cart-totals-section');
+
+		this.$totals_section.append(
+			`<div class="add-discount flex items-center pt-4 pb-4 pr-4 pl-4 text-grey pointer no-select d-none">
+				+ Add Discount
+			</div>
+			<div class="border border-grey rounded">
+				<div class="net-total flex justify-between items-center h-16 pr-8 pl-8 border-b-grey">
+					<div class="flex flex-col">
+						<div class="text-md text-dark-grey text-bold">Net Total</div>
+					</div>
+					<div class="flex flex-col text-right">
+						<div class="text-md text-dark-grey text-bold">0.00</div>
+					</div>
+				</div>
+				<div class="taxes"></div>
+				<div class="grand-total flex justify-between items-center h-16 pr-8 pl-8 border-b-grey">
+					<div class="flex flex-col">
+						<div class="text-md text-dark-grey text-bold">Grand Total</div>
+					</div>
+					<div class="flex flex-col text-right">
+						<div class="text-md text-dark-grey text-bold">0.00</div>
+					</div>
+				</div>
+				<div class="checkout-btn flex items-center justify-center h-16 pr-8 pl-8 text-center text-grey no-select pointer rounded-b text-md text-bold">
+					Checkout
+				</div>
+				<div class="edit-cart-btn flex items-center justify-center h-16 pr-8 pl-8 text-center text-grey no-select pointer d-none text-md text-bold">
+					Edit Cart
+				</div>
+			</div>`
+		)
+
+		this.$add_discount_elem = this.$component.find(".add-discount");
+    }
+    
+    make_cart_numpad() {
+		this.$numpad_section = this.$component.find('.numpad-section');
+
+		this.number_pad = new erpnext.PointOfSale.NumberPad({
+			wrapper: this.$numpad_section,
+			events: {
+				numpad_event: this.on_numpad_event.bind(this)
+			},
+			cols: 5,
+			keys: [
+				[ 1, 2, 3, 'Quantity' ],
+				[ 4, 5, 6, 'Discount' ],
+				[ 7, 8, 9, 'Rate' ],
+				[ '.', 0, 'Delete', 'Remove' ]
+			],
+			css_classes: [
+				[ '', '', '', 'col-span-2' ],
+				[ '', '', '', 'col-span-2' ],
+				[ '', '', '', 'col-span-2' ],
+				[ '', '', '', 'col-span-2 text-bold text-danger' ]
+			],
+			fieldnames_map: { 'Quantity': 'qty', 'Discount': 'discount_percentage' }
+		})
+
+		this.$numpad_section.prepend(
+			`<div class="flex mb-2 justify-between">
+				<span class="numpad-net-total"></span>
+				<span class="numpad-grand-total"></span>
+			</div>`
+		)
+
+		this.$numpad_section.append(
+			`<div class="numpad-btn checkout-btn flex items-center justify-center h-16 pr-8 pl-8 bg-primary
+				text-center text-white no-select pointer rounded text-md text-bold mt-4" data-button-value="checkout">
+					Checkout
+			</div>`
+		)
+    }
+    
+    bind_events() {
+		const me = this;
+		this.$customer_section.on('click', '.add-remove-customer', function (e) {
+			const customer_info_is_visible = me.$cart_container.hasClass('d-none');
+			customer_info_is_visible ? 
+				me.toggle_customer_info(false) : me.reset_customer_selector();
+		});
+
+		this.$customer_section.on('click', '.customer-header', function(e) {
+			// don't triggger the event if .add-remove-customer btn is clicked which is under .customer-header
+			if ($(e.target).closest('.add-remove-customer').length) return;
+
+			const show = !me.$cart_container.hasClass('d-none');
+			me.toggle_customer_info(show);
+		});
+
+		this.$cart_items_wrapper.on('click', '.cart-item-wrapper', function() {
+			const $cart_item = $(this);
+
+			me.toggle_item_highlight(this);
+
+			const payment_section_hidden = me.$totals_section.find('.edit-cart-btn').hasClass('d-none');
+			if (!payment_section_hidden) {
+				// payment section is visible
+				// edit cart first and then open item details section
+				me.$totals_section.find(".edit-cart-btn").click();
+			}
+
+			const item_code = unescape($cart_item.attr('data-item-code'));
+			const batch_no = unescape($cart_item.attr('data-batch-no'));
+			const uom = unescape($cart_item.attr('data-uom'));
+			me.events.cart_item_clicked(item_code, batch_no, uom);
+			this.numpad_value = '';
+		});
+
+		this.$component.on('click', '.checkout-btn', function() {
+			if (!$(this).hasClass('bg-primary')) return;
+			
+			me.events.checkout();
+			me.toggle_checkout_btn(false);
+
+			me.$add_discount_elem.removeClass("d-none");
+		});
+
+		this.$totals_section.on('click', '.edit-cart-btn', () => {
+			this.events.edit_cart();
+			this.toggle_checkout_btn(true);
+
+			this.$add_discount_elem.addClass("d-none");
+		});
+
+		this.$component.on('click', '.add-discount', () => {
+			const can_edit_discount = this.$add_discount_elem.find('.edit-discount').length;
+
+			if(!this.discount_field || can_edit_discount) this.show_discount_control();
+		});
+
+		frappe.ui.form.on("POS Invoice", "paid_amount", frm => {
+			// called when discount is applied
+			this.update_totals_section(frm);
+		});
+	}
+
+	attach_shortcuts() {
+		for (let row of this.number_pad.keys) {
+			for (let btn of row) {
+				let shortcut_key = `ctrl+${frappe.scrub(String(btn))[0]}`;
+				if (btn === 'Delete') shortcut_key = 'ctrl+backspace';
+				if (btn === 'Remove') shortcut_key = 'shift+ctrl+backspace'
+				if (btn === '.') shortcut_key = 'ctrl+>';
+
+				// to account for fieldname map
+				const fieldname = this.number_pad.fieldnames[btn] ? this.number_pad.fieldnames[btn] : 
+					typeof btn === 'string' ? frappe.scrub(btn) : btn;
+
+				frappe.ui.keys.on(`${shortcut_key}`, () => {
+					const cart_is_visible = this.$component.is(":visible");
+					if (cart_is_visible && this.item_is_selected && this.$numpad_section.is(":visible")) {
+						this.$numpad_section.find(`.numpad-btn[data-button-value="${fieldname}"]`).click();
+					} 
+				})
+			}
+		}
+
+		frappe.ui.keys.on("ctrl+enter", () => {
+			const cart_is_visible = this.$component.is(":visible");
+			const payment_section_hidden = this.$totals_section.find('.edit-cart-btn').hasClass('d-none');
+			if (cart_is_visible && payment_section_hidden) {
+				this.$component.find(".checkout-btn").click();
+			}
+		});
+	}
+	
+	toggle_item_highlight(item) {
+		const $cart_item = $(item);
+		const item_is_highlighted = $cart_item.hasClass("shadow");
+
+		if (!item || item_is_highlighted) {
+			this.item_is_selected = false;
+			this.$cart_container.find('.cart-item-wrapper').removeClass("shadow").css("opacity", "1");
+		} else {
+			$cart_item.addClass("shadow");
+			this.item_is_selected = true;
+			this.$cart_container.find('.cart-item-wrapper').css("opacity", "1");
+			this.$cart_container.find('.cart-item-wrapper').not(item).removeClass("shadow").css("opacity", "0.65");
+		}
+		// highlight with inner shadow
+		// $cart_item.addClass("shadow-inner bg-selected");
+		// me.$cart_container.find('.cart-item-wrapper').not(this).removeClass("shadow-inner bg-selected");
+	}
+
+	make_customer_selector() {
+		this.$customer_section.html(`<div class="customer-search-field flex flex-1 items-center"></div>`);
+		const me = this;
+		const query = { query: 'erpnext.controllers.queries.customer_query' };
+		const allowed_customer_group = this.events.get_allowed_customer_group() || [];
+		if (allowed_customer_group.length) {
+			query.filters = {
+				customer_group: ['in', allowed_customer_group]
+			}
+		}
+		this.customer_field = frappe.ui.form.make_control({
+			df: {
+				label: __('Customer'),
+				fieldtype: 'Link',
+				options: 'Customer',
+				placeholder: __('Search by customer name, phone, email.'),
+				get_query: () => query,
+				onchange: function() {
+					if (this.value) {
+						const frm = me.events.get_frm();
+						frappe.dom.freeze();
+						frappe.model.set_value(frm.doc.doctype, frm.doc.name, 'customer', this.value);
+						frm.script_manager.trigger('customer', frm.doc.doctype, frm.doc.name).then(() => {
+							frappe.run_serially([
+								() => me.fetch_customer_details(this.value),
+								() => me.events.customer_details_updated(me.customer_info),
+								() => me.update_customer_section(),
+								() => me.update_totals_section(),
+								() => frappe.dom.unfreeze()
+							]);
+						})
+					}
+				},
+			},
+			parent: this.$customer_section.find('.customer-search-field'),
+			render_input: true,
+		});
+		this.customer_field.toggle_label(false);
+	}
+	
+	fetch_customer_details(customer) {
+		if (customer) {
+			return new Promise((resolve) => {
+				frappe.db.get_value('Customer', customer, ["email_id", "mobile_no", "image", "loyalty_program"]).then(({ message }) => {
+					const { loyalty_program } = message;
+					// if loyalty program then fetch loyalty points too
+					if (loyalty_program) {
+						frappe.call({
+							method: "erpnext.accounts.doctype.loyalty_program.loyalty_program.get_loyalty_program_details_with_points",
+							args: { customer, loyalty_program, "silent": true },
+							callback: (r) => {
+								const { loyalty_points, conversion_factor } = r.message;
+								if (!r.exc) {
+									this.customer_info = { ...message, customer, loyalty_points, conversion_factor };
+									resolve();
+								}
+							}
+						});
+					} else {
+						this.customer_info = { ...message, customer };
+						resolve();
+					}
+				});
+			});
+		} else {
+			return new Promise((resolve) => {
+				this.customer_info = {}
+				resolve();
+			});
+		}
+	}
+
+	show_discount_control() {
+		this.$add_discount_elem.removeClass("pr-4 pl-4");
+		this.$add_discount_elem.html(
+			`<div class="add-dicount-field flex flex-1 items-center"></div>
+			<div class="submit-field flex items-center"></div>`
+		);
+		const me = this;
+
+		this.discount_field = frappe.ui.form.make_control({
+			df: {
+				label: __('Discount'),
+				fieldtype: 'Data',
+				placeholder: __('Enter discount percentage.'),
+				onchange: function() {
+					if (this.value || this.value == 0) {
+						const frm = me.events.get_frm();
+						frappe.model.set_value(frm.doc.doctype, frm.doc.name, 'additional_discount_percentage', this.value);
+						me.hide_discount_control(this.value);
+					}
+				},
+			},
+			parent: this.$add_discount_elem.find('.add-dicount-field'),
+			render_input: true,
+		});
+		this.discount_field.toggle_label(false);
+		this.discount_field.set_focus();
+	}
+
+	hide_discount_control(discount) {
+		this.$add_discount_elem.addClass('pr-4 pl-4');
+		this.$add_discount_elem.html(
+			`<svg class="mr-2" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1" 
+				stroke-linecap="round" stroke-linejoin="round">
+				<path d="M12 20h9"/><path d="M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4L16.5 3.5z"/>
+			</svg> 
+			<div class="edit-discount p-1 pr-3 pl-3 text-dark-grey rounded w-fit bg-green-200 mb-2">
+				${String(discount).bold()}% off
+			</div>
+			`
+		);
+	}
+    
+    update_customer_section() {
+		const { customer, email_id='', mobile_no='', image } = this.customer_info || {};
+
+		if (customer) {
+			this.$customer_section.addClass('border pr-4 pl-4').html(
+				`<div class="customer-details flex flex-col">
+					<div class="customer-header flex items-center rounded h-18 pointer">
+						${get_customer_image()}
+						<div class="customer-name flex flex-col flex-1 f-shrink-1 overflow-hidden whitespace-nowrap">
+							<div class="text-md text-dark-grey text-bold">${customer}</div>
+							${get_customer_description()}
+						</div>
+						<div class="f-shrink-0 add-remove-customer flex items-center pointer" data-customer="${escape(customer)}">
+							<svg width="32" height="32" viewBox="0 0 14 14" fill="none">
+								<path d="M4.93764 4.93759L7.00003 6.99998M9.06243 9.06238L7.00003 6.99998M7.00003 6.99998L4.93764 9.06238L9.06243 4.93759" stroke="#8D99A6"/>
+							</svg>
+						</div>
+					</div>
+				</div>`
+			);
+		} else {
+            // reset customer selector
+			this.reset_customer_selector();
+		}
+
+		function get_customer_description() {
+			if (!email_id && !mobile_no) {
+				return `<div class="text-grey-200 italic">Click to add email / phone</div>`
+			} else if (email_id && !mobile_no) {
+				return `<div class="text-grey">${email_id}</div>`
+			} else if (mobile_no && !email_id) {
+				return `<div class="text-grey">${mobile_no}</div>`
+			} else {
+				return `<div class="text-grey">${email_id} | ${mobile_no}</div>`
+			}
+		}
+
+		function get_customer_image() {
+			if (image) {
+				return `<div class="icon flex items-center justify-center w-12 h-12 rounded bg-light-grey mr-4 text-grey-200">
+							<img class="h-full" src="${image}" alt="${image}" style="object-fit: cover;">
+						</div>`
+			} else {
+				return `<div class="icon flex items-center justify-center w-12 h-12 rounded bg-light-grey mr-4 text-grey-200 text-md">
+							${frappe.get_abbr(customer)}
+						</div>`
+			}
+		}
+    }
+    
+    update_totals_section(frm) {
+		if (!frm) frm = this.events.get_frm();
+
+		this.render_net_total(frm.doc.base_net_total);
+		this.render_grand_total(frm.doc.base_grand_total);
+
+		const taxes = frm.doc.taxes.map(t => { return { description: t.description, rate: t.rate }})
+		this.render_taxes(frm.doc.base_total_taxes_and_charges, taxes);
+    }
+    
+    render_net_total(value) {
+		const currency = this.events.get_frm().doc.currency;
+		this.$totals_section.find('.net-total').html(
+			`<div class="flex flex-col">
+				<div class="text-md text-dark-grey text-bold">Net Total</div>
+			</div>
+			<div class="flex flex-col text-right">
+				<div class="text-md text-dark-grey text-bold">${format_currency(value, currency)}</div>
+			</div>`
+		)
+
+		this.$numpad_section.find('.numpad-net-total').html(`Net Total: <span class="text-bold">${format_currency(value, currency)}</span>`)
+    }
+    
+    render_grand_total(value) {
+		const currency = this.events.get_frm().doc.currency;
+		this.$totals_section.find('.grand-total').html(
+			`<div class="flex flex-col">
+				<div class="text-md text-dark-grey text-bold">Grand Total</div>
+			</div>
+			<div class="flex flex-col text-right">
+				<div class="text-md text-dark-grey text-bold">${format_currency(value, currency)}</div>
+			</div>`
+		)
+
+		this.$numpad_section.find('.numpad-grand-total').html(`Grand Total: <span class="text-bold">${format_currency(value, currency)}</span>`)
+	}
+
+	render_taxes(value, taxes) {
+		if (taxes.length) {
+			const currency = this.events.get_frm().doc.currency;
+			this.$totals_section.find('.taxes').html(
+				`<div class="flex items-center justify-between h-16 pr-8 pl-8 border-b-grey">
+					<div class="flex">
+						<div class="text-md text-dark-grey text-bold w-fit">Tax Charges</div>
+						<div class="flex ml-6 text-dark-grey">
+						${	
+							taxes.map((t, i) => {
+								let margin_left = '';
+								if (i !== 0) margin_left = 'ml-2';
+								return `<span class="border-grey p-1 pl-2 pr-2 rounded ${margin_left}">${t.description}</span>`
+							}).join('')
+						}
+						</div>
+					</div>
+					<div class="flex flex-col text-right">
+						<div class="text-md text-dark-grey text-bold">${format_currency(value, currency)}</div>
+					</div>
+				</div>`
+			)
+		} else {
+			this.$totals_section.find('.taxes').html('')
+		}
+    }
+
+    get_cart_item({ item_code, batch_no, uom }) {
+		const batch_attr = `[data-batch-no="${escape(batch_no)}"]`;
+		const item_code_attr = `[data-item-code="${escape(item_code)}"]`;
+		const uom_attr = `[data-uom=${escape(uom)}]`;
+
+        const item_selector = batch_no ? 
+            `.cart-item-wrapper${batch_attr}${uom_attr}` : `.cart-item-wrapper${item_code_attr}${uom_attr}`;
+            
+        return this.$cart_items_wrapper.find(item_selector);
+    }
+    
+    update_item_html(item, remove_item) {
+		const $item = this.get_cart_item(item);
+
+		if (remove_item) {
+			$item && $item.remove();
+		} else {
+			const { item_code, batch_no, uom } = item;
+			const search_field = batch_no ? 'batch_no' : 'item_code';
+			const search_value = batch_no || item_code;
+			const item_row = this.events.get_frm().doc.items.find(i => i[search_field] === search_value && i.uom === uom);
+			
+			this.render_cart_item(item_row, $item);
+		}
+
+		const no_of_cart_items = this.$cart_items_wrapper.children().length;
+		no_of_cart_items > 0 && this.highlight_checkout_btn(no_of_cart_items > 0);
+        
+		this.update_empty_cart_section(no_of_cart_items);
+	}
+    
+    render_cart_item(item_data, $item_to_update) {
+		const currency = this.events.get_frm().doc.currency;
+		const me = this;
+		
+        if (!$item_to_update.length) {
+            this.$cart_items_wrapper.append(
+                `<div class="cart-item-wrapper flex items-center h-18 pr-4 pl-4 rounded border-grey pointer no-select" 
+						data-item-code="${escape(item_data.item_code)}" data-uom="${escape(item_data.uom)}"
+						data-batch-no="${escape(item_data.batch_no || '')}">
+                </div>`
+            )
+            $item_to_update = this.get_cart_item(item_data);
+        }
+
+		$item_to_update.html(
+			`<div class="flex flex-col flex-1 f-shrink-1 overflow-hidden whitespace-nowrap">
+                <div class="text-md text-dark-grey text-bold">
+                    ${item_data.item_name}
+                </div>
+                ${get_description_html()}
+            </div>
+                ${get_rate_discount_html()}
+            </div>`
+		)
+
+		set_dynamic_rate_header_width();
+		this.scroll_to_item($item_to_update);
+
+		function set_dynamic_rate_header_width() {
+			const rate_cols = Array.from(me.$cart_items_wrapper.find(".rate-col"));
+			me.$cart_header.find(".rate-list-header").css("width", "");
+			me.$cart_items_wrapper.find(".rate-col").css("width", "");
+			let max_width = rate_cols.reduce((max_width, elm) => {
+				if ($(elm).width() > max_width)
+					max_width = $(elm).width();
+				return max_width;
+			}, 0);
+
+			max_width += 1;
+			if (max_width == 1) max_width = "";
+
+			me.$cart_header.find(".rate-list-header").css("width", max_width);
+			me.$cart_items_wrapper.find(".rate-col").css("width", max_width);
+		}
+        
+		function get_rate_discount_html() {
+			if (item_data.rate && item_data.amount && item_data.rate !== item_data.amount) {
+				return `
+					<div class="flex f-shrink-0 ml-4 items-center">
+						<div class="flex w-8 h-8 rounded bg-light-grey mr-4 items-center justify-center font-bold f-shrink-0">
+							<span>${item_data.qty || 0}</span>
+						</div>
+						<div class="rate-col flex flex-col f-shrink-0 text-right">
+							<div class="text-md text-dark-grey text-bold">${format_currency(item_data.amount, currency)}</div>
+							<div class="text-md-0 text-dark-grey">${format_currency(item_data.rate, currency)}</div>
+						</div>
+					</div>`
+			} else {
+				return `
+					<div class="flex f-shrink-0 ml-4 text-right">
+						<div class="flex w-8 h-8 rounded bg-light-grey mr-4 items-center justify-center font-bold f-shrink-0">
+							<span>${item_data.qty || 0}</span>
+						</div>
+						<div class="rate-col flex flex-col f-shrink-0 text-right">
+							<div class="text-md text-dark-grey text-bold">${format_currency(item_data.rate, currency)}</div>
+						</div>
+					</div>`
+			}
+		}
+
+		function get_description_html() {
+			if (item_data.description) {
+				if (item_data.description.indexOf('<div>') != -1) {
+					try {
+						item_data.description = $(item_data.description).text();
+					} catch (error) {
+						item_data.description = item_data.description.replace(/<div>/g, ' ').replace(/<\/div>/g, ' ').replace(/ +/g, ' ');
+					}
+				}
+				item_data.description = frappe.ellipsis(item_data.description, 45);
+				return `<div class="text-grey">${item_data.description}</div>`
+			}
+			return ``;
+		}
+	}
+
+	scroll_to_item($item) {
+		if ($item.length === 0) return;
+		const scrollTop = $item.offset().top - this.$cart_items_wrapper.offset().top + this.$cart_items_wrapper.scrollTop();
+		this.$cart_items_wrapper.animate({ scrollTop });
+	}
+	
+	update_selector_value_in_cart_item(selector, value, item) {
+		const $item_to_update = this.get_cart_item(item);
+		$item_to_update.attr(`data-${selector}`, value);
+	}
+
+    toggle_checkout_btn(show_checkout) {
+		if (show_checkout) {
+			this.$totals_section.find('.checkout-btn').removeClass('d-none');
+			this.$totals_section.find('.edit-cart-btn').addClass('d-none');
+		} else {
+			this.$totals_section.find('.checkout-btn').addClass('d-none');
+			this.$totals_section.find('.edit-cart-btn').removeClass('d-none');
+		}
+	}
+
+    highlight_checkout_btn(toggle) {
+		const has_primary_class = this.$totals_section.find('.checkout-btn').hasClass('bg-primary');
+		if (toggle && !has_primary_class) {
+			this.$totals_section.find('.checkout-btn').addClass('bg-primary text-white text-lg');
+		} else if (!toggle && has_primary_class) {
+			this.$totals_section.find('.checkout-btn').removeClass('bg-primary text-white text-lg');
+		}
+	}
+    
+    update_empty_cart_section(no_of_cart_items) {
+		const $no_item_element = this.$cart_items_wrapper.find('.no-item-wrapper');
+
+		// if cart has items and no item is present
+		no_of_cart_items > 0 && $no_item_element && $no_item_element.remove()
+			&& this.$cart_items_wrapper.removeClass('mt-4 border-grey border-dashed') && this.$cart_header.removeClass('d-none');
+
+		no_of_cart_items === 0 && !$no_item_element.length && this.make_no_items_placeholder();
+    }
+    
+    on_numpad_event($btn) {
+		const current_action = $btn.attr('data-button-value');
+		const action_is_field_edit = ['qty', 'discount_percentage', 'rate'].includes(current_action);
+
+		this.highlight_numpad_btn($btn, current_action);
+
+        const action_is_pressed_twice = this.prev_action === current_action;
+        const first_click_event = !this.prev_action;
+        const field_to_edit_changed = this.prev_action && this.prev_action != current_action;
+
+		if (action_is_field_edit) {
+
+			if (first_click_event || field_to_edit_changed) {
+                this.prev_action = current_action;
+			} else if (action_is_pressed_twice) {
+				this.prev_action = undefined;
+			}
+            this.numpad_value = '';
+            
+		} else if (current_action === 'checkout') {
+			this.prev_action = undefined;
+			this.toggle_item_highlight();
+			this.events.numpad_event(undefined, current_action);
+			return;
+		} else if (current_action === 'remove') {
+			this.prev_action = undefined;
+			this.toggle_item_highlight();
+			this.events.numpad_event(undefined, current_action);
+			return;
+		} else {
+			this.numpad_value = current_action === 'delete' ? this.numpad_value.slice(0, -1) : this.numpad_value + current_action;
+			this.numpad_value = this.numpad_value || 0;
+		}
+
+        const first_click_event_is_not_field_edit = !action_is_field_edit && first_click_event;
+
+		if (first_click_event_is_not_field_edit) {
+			frappe.show_alert({
+				indicator: 'red',
+				message: __('Please select a field to edit from numpad')
+			});
+			frappe.utils.play_sound("error");
+			return;
+		}
+		
+		if (flt(this.numpad_value) > 100 && this.prev_action === 'discount_percentage') {
+			frappe.show_alert({
+				message: __('Discount cannot be greater than 100%'),
+				indicator: 'orange'
+			});
+			frappe.utils.play_sound("error");
+			this.numpad_value = current_action;
+		}
+
+        this.events.numpad_event(this.numpad_value, this.prev_action);
+    }
+    
+    highlight_numpad_btn($btn, curr_action) {
+        const curr_action_is_highlighted = $btn.hasClass('shadow-inner');
+        const curr_action_is_action = ['qty', 'discount_percentage', 'rate', 'done'].includes(curr_action);
+
+        if (!curr_action_is_highlighted) {
+            $btn.addClass('shadow-inner bg-selected');
+        }
+        if (this.prev_action === curr_action && curr_action_is_highlighted) {
+            // if Qty is pressed twice
+            $btn.removeClass('shadow-inner bg-selected');
+        }
+        if (this.prev_action && this.prev_action !== curr_action && curr_action_is_action) {
+            // Order: Qty -> Rate then remove Qty highlight
+            const prev_btn = $(`[data-button-value='${this.prev_action}']`);
+            prev_btn.removeClass('shadow-inner bg-selected');
+        }
+        if (!curr_action_is_action || curr_action === 'done') {
+            // if numbers are clicked
+            setTimeout(() => {
+                $btn.removeClass('shadow-inner bg-selected');
+            }, 100);
+        }
+    }
+
+    toggle_numpad(show) {
+		if (show) {
+			this.$totals_section.addClass('d-none');
+			this.$numpad_section.removeClass('d-none');
+		} else {
+			this.$totals_section.removeClass('d-none');
+			this.$numpad_section.addClass('d-none');
+		}
+		this.reset_numpad();
+	}
+
+	reset_numpad() {
+		this.numpad_value = '';
+		this.prev_action = undefined;
+		this.$numpad_section.find('.shadow-inner').removeClass('shadow-inner bg-selected');
+	}
+
+	toggle_numpad_field_edit(fieldname) {
+		if (['qty', 'discount_percentage', 'rate'].includes(fieldname)) {
+			this.$numpad_section.find(`[data-button-value="${fieldname}"]`).click();
+		}
+	}
+
+	toggle_customer_info(show) {
+		if (show) {
+			this.$cart_container.addClass('d-none')
+			this.$customer_section.addClass('flex-1 scroll-y').removeClass('mb-0 border pr-4 pl-4')
+			this.$customer_section.find('.icon').addClass('w-24 h-24 text-2xl').removeClass('w-12 h-12 text-md')
+			this.$customer_section.find('.customer-header').removeClass('h-18');
+			this.$customer_section.find('.customer-details').addClass('sticky z-100 bg-white');
+
+			this.$customer_section.find('.customer-name').html(
+				`<div class="text-md text-dark-grey text-bold">${this.customer_info.customer}</div>
+				<div class="last-transacted-on text-grey-200"></div>`
+			)
+	
+			this.$customer_section.find('.customer-details').append(
+				`<div class="customer-form">
+					<div class="text-grey mt-4 mb-6">CONTACT DETAILS</div>
+					<div class="grid grid-cols-2 gap-4">
+						<div class="email_id-field"></div>
+						<div class="mobile_no-field"></div>
+						<div class="loyalty_program-field"></div>
+						<div class="loyalty_points-field"></div>
+					</div>
+					<div class="text-grey mt-4 mb-6">RECENT TRANSACTIONS</div>
+				</div>`
+			)
+			// transactions need to be in diff div from sticky elem for scrolling
+			this.$customer_section.append(`<div class="customer-transactions flex-1 rounded"></div>`)
+
+			this.render_customer_info_form();
+			this.fetch_customer_transactions();
+
+		} else {
+			this.$cart_container.removeClass('d-none');
+			this.$customer_section.removeClass('flex-1 scroll-y').addClass('mb-0 border pr-4 pl-4');
+			this.$customer_section.find('.icon').addClass('w-12 h-12 text-md').removeClass('w-24 h-24 text-2xl');
+			this.$customer_section.find('.customer-header').addClass('h-18')
+			this.$customer_section.find('.customer-details').removeClass('sticky z-100 bg-white');
+
+			this.update_customer_section();
+		}
+	}
+
+	render_customer_info_form() {
+		const $customer_form = this.$customer_section.find('.customer-form');
+
+		const dfs = [{
+			fieldname: 'email_id',
+			label: __('Email'),
+			fieldtype: 'Data',
+			options: 'email',
+			placeholder: __("Enter customer's email")
+		},{
+			fieldname: 'mobile_no',
+			label: __('Phone Number'),
+			fieldtype: 'Data',
+			placeholder: __("Enter customer's phone number")
+		},{
+			fieldname: 'loyalty_program',
+			label: __('Loyalty Program'),
+			fieldtype: 'Link',
+			options: 'Loyalty Program',
+			placeholder: __("Select Loyalty Program")
+		},{
+			fieldname: 'loyalty_points',
+			label: __('Loyalty Points'),
+			fieldtype: 'Int',
+			read_only: 1
+		}];
+
+		const me = this;
+		dfs.forEach(df => {
+			this[`customer_${df.fieldname}_field`] = frappe.ui.form.make_control({
+				df: { ...df,
+					onchange: handle_customer_field_change,
+				},
+				parent: $customer_form.find(`.${df.fieldname}-field`),
+				render_input: true,
+			});
+			this[`customer_${df.fieldname}_field`].set_value(this.customer_info[df.fieldname]);
+		})
+
+		function handle_customer_field_change() {
+			const current_value = me.customer_info[this.df.fieldname];
+			const current_customer = me.customer_info.customer;
+
+			if (this.value && current_value != this.value && this.df.fieldname != 'loyalty_points') {
+				frappe.call({
+					method: 'erpnext.selling.page.point_of_sale.point_of_sale.set_customer_info',
+					args: {
+						fieldname: this.df.fieldname,
+						customer: current_customer,
+						value: this.value
+					},
+					callback: (r) => {
+						if(!r.exc) {
+							me.customer_info[this.df.fieldname] = this.value;
+							frappe.show_alert({
+								message: __("Customer contact updated successfully."),
+								indicator: 'green'
+							});
+							frappe.utils.play_sound("submit");
+						}
+					}
+				});
+			}
+		}
+	}
+
+	fetch_customer_transactions() {
+		frappe.db.get_list('POS Invoice', { 
+			filters: { customer: this.customer_info.customer, docstatus: 1 },
+			fields: ['name', 'grand_total', 'status', 'posting_date', 'posting_time', 'currency'],
+			limit: 20
+		}).then((res) => {
+			const transaction_container = this.$customer_section.find('.customer-transactions');
+
+			if (!res.length) {
+				transaction_container.removeClass('flex-1 border rounded').html(
+					`<div class="text-grey text-center">No recent transactions found</div>`
+				)
+				return;
+			};
+
+			const elapsed_time = moment(res[0].posting_date+" "+res[0].posting_time).fromNow();
+			this.$customer_section.find('.last-transacted-on').html(`Last transacted ${elapsed_time}`);
+
+			res.forEach(invoice => {
+				const posting_datetime = moment(invoice.posting_date+" "+invoice.posting_time).format("Do MMMM, h:mma");
+				let indicator_color = '';
+
+				if (in_list(['Paid', 'Consolidated'], invoice.status)) (indicator_color = 'green');
+				if (invoice.status === 'Draft') (indicator_color = 'red');
+				if (invoice.status === 'Return') (indicator_color = 'grey');
+
+				transaction_container.append(
+					`<div class="invoice-wrapper flex p-3 justify-between border-grey rounded pointer no-select" data-invoice-name="${escape(invoice.name)}">
+						<div class="flex flex-col justify-end">
+							<div class="text-dark-grey text-bold overflow-hidden whitespace-nowrap mb-2">${invoice.name}</div>
+							<div class="flex items-center f-shrink-1 text-dark-grey overflow-hidden whitespace-nowrap">
+								${posting_datetime}
+							</div>
+						</div>
+						<div class="flex flex-col text-right">
+							<div class="f-shrink-0 text-md text-dark-grey text-bold ml-4">
+								${format_currency(invoice.grand_total, invoice.currency, 0) || 0}
+							</div>
+							<div class="f-shrink-0 text-grey ml-4 text-bold indicator ${indicator_color}">${invoice.status}</div>
+						</div>
+					</div>`
+				)
+			});
+		})
+	}
+
+	load_invoice() {
+		const frm = this.events.get_frm();
+		this.fetch_customer_details(frm.doc.customer).then(() => {
+			this.events.customer_details_updated(this.customer_info);
+			this.update_customer_section();
+		})
+		
+		this.$cart_items_wrapper.html('');
+		if (frm.doc.items.length) {
+			frm.doc.items.forEach(item => {
+				this.update_item_html(item);
+			});
+		} else {
+			this.make_no_items_placeholder();
+			this.highlight_checkout_btn(false);
+		}
+
+		this.update_totals_section(frm);
+
+		if(frm.doc.docstatus === 1) {
+			this.$totals_section.find('.checkout-btn').addClass('d-none');
+			this.$totals_section.find('.edit-cart-btn').addClass('d-none');
+			this.$totals_section.find('.grand-total').removeClass('border-b-grey');
+		} else {
+			this.$totals_section.find('.checkout-btn').removeClass('d-none');
+			this.$totals_section.find('.edit-cart-btn').addClass('d-none');
+			this.$totals_section.find('.grand-total').addClass('border-b-grey');
+		}
+
+		this.toggle_component(true);
+	}
+
+	toggle_component(show) {
+		show ? this.$component.removeClass('d-none') : this.$component.addClass('d-none');
+    }
+    
+}
\ No newline at end of file
diff --git a/erpnext/selling/page/point_of_sale/pos_item_details.js b/erpnext/selling/page/point_of_sale/pos_item_details.js
new file mode 100644
index 0000000..86a1be9
--- /dev/null
+++ b/erpnext/selling/page/point_of_sale/pos_item_details.js
@@ -0,0 +1,394 @@
+erpnext.PointOfSale.ItemDetails = class {
+    constructor({ wrapper, events }) {
+		this.wrapper = wrapper;
+        this.events = events;
+        this.current_item = {};
+
+        this.init_component();
+    }
+
+    init_component() {
+        this.prepare_dom();
+        this.init_child_components();
+		this.bind_events();
+		this.attach_shortcuts();
+    }
+
+    prepare_dom() {
+        this.wrapper.append(
+            `<section class="col-span-4 flex shadow rounded item-details bg-white mx-h-70 h-100 d-none"></section>`
+        )
+
+        this.$component = this.wrapper.find('.item-details');
+    }
+
+    init_child_components() {
+		this.$component.html(
+			`<div class="details-container flex flex-col p-8 rounded w-full">
+				<div class="flex justify-between mb-2">
+					<div class="text-grey">ITEM DETAILS</div>
+					<div class="close-btn text-grey hover-underline pointer no-select">Close</div>
+				</div>
+				<div class="item-defaults flex">
+					<div class="flex-1 flex flex-col justify-end mr-4 mb-2">
+						<div class="item-name text-xl font-weight-450"></div>
+						<div class="item-description text-md-0 text-grey-200"></div>
+						<div class="item-price text-xl font-bold"></div>
+					</div>
+					<div class="item-image flex items-center justify-center w-46 h-46 bg-light-grey rounded ml-4 text-6xl text-grey-100"></div>
+				</div>
+				<div class="discount-section flex items-center"></div>
+				<div class="text-grey mt-4 mb-6">STOCK DETAILS</div>
+				<div class="form-container grid grid-cols-2 row-gap-2 col-gap-4 grid-auto-row"></div>
+			</div>`
+		)
+
+		this.$item_name = this.$component.find('.item-name');
+		this.$item_description = this.$component.find('.item-description');
+		this.$item_price = this.$component.find('.item-price');
+		this.$item_image = this.$component.find('.item-image');
+		this.$form_container = this.$component.find('.form-container');
+		this.$dicount_section = this.$component.find('.discount-section');
+    }
+
+    toggle_item_details_section(item) {
+		const { item_code, batch_no, uom } = this.current_item; 
+		const item_code_is_same = item && item_code === item.item_code;
+		const batch_is_same = item && batch_no == item.batch_no;
+		const uom_is_same = item && uom === item.uom;
+
+        this.item_has_changed = !item ? false : item_code_is_same && batch_is_same && uom_is_same ? false : true;
+
+        this.events.toggle_item_selector(this.item_has_changed);
+		this.toggle_component(this.item_has_changed);
+        
+		if (this.item_has_changed) {
+            this.doctype = item.doctype;
+			this.item_meta = frappe.get_meta(this.doctype);
+			this.name = item.name;
+			this.item_row = item;
+            this.currency = this.events.get_frm().doc.currency;
+            
+            this.current_item = { item_code: item.item_code, batch_no: item.batch_no, uom: item.uom };
+            
+			this.render_dom(item);
+			this.render_discount_dom(item);
+			this.render_form(item);
+		} else {
+			this.validate_serial_batch_item();
+			this.current_item = {};
+		}
+	}
+	
+	validate_serial_batch_item() {
+		const doc = this.events.get_frm().doc;
+		const item_row = doc.items.find(item => item.name === this.name);
+
+		if (!item_row) return;
+
+		const serialized = item_row.has_serial_no;
+		const batched = item_row.has_batch_no;
+		const no_serial_selected = !item_row.serial_no;
+		const no_batch_selected = !item_row.batch_no;
+
+		if ((serialized && no_serial_selected) || (batched && no_batch_selected) || 
+			(serialized && batched && (no_batch_selected || no_serial_selected))) {
+
+			frappe.show_alert({
+				message: __("Item will be removed since no serial / batch no selected."),
+				indicator: 'orange'
+			});
+			frappe.utils.play_sound("cancel");
+			this.events.remove_item_from_cart();
+		}
+	}
+    
+    render_dom(item) {
+        let { item_code ,item_name, description, image, price_list_rate } = item;
+
+		function get_description_html() {
+			if (description) {
+				description = description.indexOf('...') === -1 && description.length > 75 ? description.substr(0, 73) + '...' : description;
+				return description;
+			}
+			return ``;
+        }
+        
+		this.$item_name.html(item_name);
+		this.$item_description.html(get_description_html());
+		this.$item_price.html(format_currency(price_list_rate, this.currency));
+		if (image) {
+			this.$item_image.html(
+				`<img class="h-full" src="${image}" alt="${image}" style="object-fit: cover;">`
+			);
+		} else {
+			this.$item_image.html(frappe.get_abbr(item_code));
+		}
+
+    }
+    
+    render_discount_dom(item) {
+		if (item.discount_percentage) {
+			this.$dicount_section.html(
+				`<div class="text-grey line-through mr-4 text-md mb-2">
+					${format_currency(item.price_list_rate, this.currency)}
+				</div>
+				<div class="p-1 pr-3 pl-3 rounded w-fit text-bold bg-green-200 mb-2">
+					${item.discount_percentage}% off
+				</div>`
+			)
+			this.$item_price.html(format_currency(item.rate, this.currency));
+		} else {
+			this.$dicount_section.html(``)
+		}
+    }
+
+    render_form(item) {
+		const fields_to_display = this.get_form_fields(item);
+		this.$form_container.html('');
+
+		fields_to_display.forEach((fieldname, idx) => {
+			this.$form_container.append(
+				`<div class="">
+					<div class="item_detail_field ${fieldname}-control" data-fieldname="${fieldname}"></div>
+				</div>`
+			)
+
+			const field_meta = this.item_meta.fields.find(df => df.fieldname === fieldname);
+			fieldname === 'discount_percentage' ? (field_meta.label = __('Discount (%)')) : '';
+			const me = this;
+            
+			this[`${fieldname}_control`] = frappe.ui.form.make_control({
+				df: { 
+					...field_meta, 
+					onchange: function() {
+						me.events.form_updated(me.doctype, me.name, fieldname, this.value);
+					}
+				},
+				parent: this.$form_container.find(`.${fieldname}-control`),
+				render_input: true,
+			})
+			this[`${fieldname}_control`].set_value(item[fieldname]);
+		});
+
+		this.make_auto_serial_selection_btn(item);
+
+		this.bind_custom_control_change_event();
+    }
+
+    get_form_fields(item) {
+		const fields = ['qty', 'uom', 'rate', 'price_list_rate', 'discount_percentage', 'warehouse', 'actual_qty'];
+		if (item.has_serial_no) fields.push('serial_no');
+		if (item.has_batch_no) fields.push('batch_no');
+		return fields;
+	}
+
+    make_auto_serial_selection_btn(item) {
+		if (item.has_serial_no) {
+			this.$form_container.append(
+				`<div class="grid-filler no-select"></div>`
+			)
+			if (!item.has_batch_no) {
+				this.$form_container.append(
+					`<div class="grid-filler no-select"></div>`
+				)	
+			}
+			this.$form_container.append(
+				`<div class="auto-fetch-btn bg-grey-100 border border-grey text-bold rounded pt-3 pb-3 pl-6 pr-8 text-grey pointer no-select mt-2"
+						style="height: 3.3rem">
+					Auto Fetch Serial Numbers
+				</div>`
+			)
+			this.$form_container.find('.serial_no-control').find('textarea').css('height', '9rem');
+			this.$form_container.find('.serial_no-control').parent().addClass('row-span-2');
+		}
+	}
+    
+    bind_custom_control_change_event() {
+		const me = this;
+		if (this.rate_control) {
+			this.rate_control.df.onchange = function() {
+				if (this.value) {
+					me.events.form_updated(me.doctype, me.name, 'rate', this.value).then(() => {
+						const item_row = frappe.get_doc(me.doctype, me.name);
+						const doc = me.events.get_frm().doc;
+
+						me.$item_price.html(format_currency(item_row.rate, doc.currency));
+						me.render_discount_dom(item_row);
+					});
+				}
+			}
+		}
+
+		if (this.warehouse_control) {
+			this.warehouse_control.df.reqd = 1;
+			this.warehouse_control.df.onchange = function() {
+				if (this.value) {
+					me.events.form_updated(me.doctype, me.name, 'warehouse', this.value).then(() => {
+						me.item_stock_map = me.events.get_item_stock_map();
+						const available_qty = me.item_stock_map[me.item_row.item_code][this.value];
+						if (available_qty === undefined) {
+							me.events.get_available_stock(me.item_row.item_code, this.value).then(() => {
+								// item stock map is updated now reset warehouse
+								me.warehouse_control.set_value(this.value);
+							})
+						} else if (available_qty === 0) {
+							me.warehouse_control.set_value('');
+							frappe.throw(__(`Item Code: ${me.item_row.item_code.bold()} is not available under warehouse ${this.value.bold()}.`));
+						}
+						me.actual_qty_control.set_value(available_qty);
+					});
+				}
+			}
+			this.warehouse_control.refresh();
+		}
+
+		if (this.discount_percentage_control) {
+			this.discount_percentage_control.df.onchange = function() {
+				if (this.value) {
+					me.events.form_updated(me.doctype, me.name, 'discount_percentage', this.value).then(() => {
+						const item_row = frappe.get_doc(me.doctype, me.name);
+						me.rate_control.set_value(item_row.rate);
+					});
+				}
+			}
+		}
+
+		if (this.serial_no_control) {
+			this.serial_no_control.df.reqd = 1;
+			this.serial_no_control.df.onchange = async function() {
+				!me.current_item.batch_no && await me.auto_update_batch_no();
+				me.events.form_updated(me.doctype, me.name, 'serial_no', this.value);
+			}
+			this.serial_no_control.refresh();
+		}
+
+		if (this.batch_no_control) {
+			this.batch_no_control.df.reqd = 1;
+			this.batch_no_control.df.get_query = () => {
+				return {
+					query: 'erpnext.controllers.queries.get_batch_no',
+					filters: {
+						item_code: me.item_row.item_code,
+						warehouse: me.item_row.warehouse
+					}
+				}
+			};
+			this.batch_no_control.df.onchange = function() {
+				me.events.set_value_in_current_cart_item('batch-no', this.value);
+                me.events.form_updated(me.doctype, me.name, 'batch_no', this.value);
+                me.current_item.batch_no = this.value;
+			}
+			this.batch_no_control.refresh();
+		}
+
+		if (this.uom_control) {
+			this.uom_control.df.onchange = function() {
+				me.events.set_value_in_current_cart_item('uom', this.value);
+				me.events.form_updated(me.doctype, me.name, 'uom', this.value);
+				me.current_item.uom = this.value;
+			}
+		}
+    }
+    
+    async auto_update_batch_no() {
+		if (this.serial_no_control && this.batch_no_control) {
+			const selected_serial_nos = this.serial_no_control.get_value().split(`\n`).filter(s => s);
+			if (!selected_serial_nos.length) return;
+
+			// find batch nos of the selected serial no 
+			const serials_with_batch_no = await frappe.db.get_list("Serial No", {
+				filters: { 'name': ["in", selected_serial_nos]},
+				fields: ["batch_no", "name"]
+			});
+			const batch_serial_map = serials_with_batch_no.reduce((acc, r) => {
+				acc[r.batch_no] || (acc[r.batch_no] = []);
+				acc[r.batch_no] = [...acc[r.batch_no], r.name];
+				return acc;
+			}, {});
+			// set current item's batch no and serial no
+			const batch_no = Object.keys(batch_serial_map)[0];
+			const batch_serial_nos = batch_serial_map[batch_no].join(`\n`);
+			// eg. 10 selected serial no. -> 5 belongs to first batch other 5 belongs to second batch
+            const serial_nos_belongs_to_other_batch = selected_serial_nos.length !== batch_serial_map[batch_no].length;
+            
+            const current_batch_no = this.batch_no_control.get_value();
+			current_batch_no != batch_no && await this.batch_no_control.set_value(batch_no);
+
+			if (serial_nos_belongs_to_other_batch) {
+				this.serial_no_control.set_value(batch_serial_nos);
+				this.qty_control.set_value(batch_serial_map[batch_no].length);
+			}
+
+			delete batch_serial_map[batch_no];
+
+			if (serial_nos_belongs_to_other_batch)
+				this.events.clone_new_batch_item_in_frm(batch_serial_map, this.current_item);
+		}
+	}
+    
+    bind_events() {
+		this.bind_auto_serial_fetch_event();
+		this.bind_fields_to_numpad_fields();
+
+		this.$component.on('click', '.close-btn', () => {
+			this.events.close_item_details();
+		});
+	}
+
+	attach_shortcuts() {
+		frappe.ui.keys.on("escape", () => {
+			const item_details_visible = this.$component.is(":visible");
+			if (item_details_visible) {
+				this.events.close_item_details();
+			}
+		});
+	}
+
+    bind_fields_to_numpad_fields() {
+		const me = this;
+		this.$form_container.on('click', '.input-with-feedback', function() {
+			const fieldname = $(this).attr('data-fieldname');
+			if (this.last_field_focused != fieldname) {
+				me.events.item_field_focused(fieldname);
+				this.last_field_focused = fieldname;
+			}
+		});
+	}
+    
+    bind_auto_serial_fetch_event() {
+		this.$form_container.on('click', '.auto-fetch-btn', () => {
+			this.batch_no_control.set_value('');
+			let qty = this.qty_control.get_value();
+			let numbers = frappe.call({
+				method: "erpnext.stock.doctype.serial_no.serial_no.auto_fetch_serial_number",
+				args: {
+					qty,
+					item_code: this.current_item.item_code,
+					warehouse: this.warehouse_control.get_value() || '',
+					batch_nos: this.current_item.batch_no || '',
+					for_doctype: 'POS Invoice'
+				}
+			});
+
+			numbers.then((data) => {
+				let auto_fetched_serial_numbers = data.message;
+				let records_length = auto_fetched_serial_numbers.length;
+				if (!records_length) {
+					const warehouse = this.warehouse_control.get_value().bold();
+					frappe.msgprint(__(`Serial numbers unavailable for Item ${this.current_item.item_code.bold()} 
+						under warehouse ${warehouse}. Please try changing warehouse.`));
+				} else if (records_length < qty) {
+					frappe.msgprint(`Fetched only ${records_length} available serial numbers.`);
+					this.qty_control.set_value(records_length);
+				}
+                numbers = auto_fetched_serial_numbers.join(`\n`);
+				this.serial_no_control.set_value(numbers);
+			});
+		})
+	}
+
+	toggle_component(show) {
+		show ? this.$component.removeClass('d-none') : this.$component.addClass('d-none');
+    }
+}
\ No newline at end of file
diff --git a/erpnext/selling/page/point_of_sale/pos_item_selector.js b/erpnext/selling/page/point_of_sale/pos_item_selector.js
new file mode 100644
index 0000000..ee0c06d
--- /dev/null
+++ b/erpnext/selling/page/point_of_sale/pos_item_selector.js
@@ -0,0 +1,265 @@
+erpnext.PointOfSale.ItemSelector = class {
+    constructor({ frm, wrapper, events, pos_profile }) {
+		this.wrapper = wrapper;
+		this.events = events;
+        this.pos_profile = pos_profile;
+        
+        this.inti_component();
+    }
+    
+    inti_component() {
+        this.prepare_dom();
+        this.make_search_bar();
+        this.load_items_data();
+        this.bind_events();
+        this.attach_shortcuts();
+    }
+
+    prepare_dom() {
+		this.wrapper.append(
+            `<section class="col-span-6 flex shadow rounded items-selector bg-white mx-h-70 h-100">
+                <div class="flex flex-col rounded w-full scroll-y">
+                    <div class="filter-section flex p-8 pb-2 bg-white sticky z-100">
+                        <div class="search-field flex f-grow-3 mr-8 items-center text-grey"></div>
+                        <div class="item-group-field flex f-grow-1 items-center text-grey text-bold"></div>
+                    </div>
+                    <div class="flex flex-1 flex-col p-8 pt-2">
+                        <div class="text-grey mb-6">ALL ITEMS</div>
+                        <div class="items-container grid grid-cols-4 gap-8">
+                        </div>					
+                    </div>
+                </div>
+            </section>`
+        );
+        
+        this.$component = this.wrapper.find('.items-selector');
+    }
+
+    async load_items_data() {
+        if (!this.item_group) {
+            const res = await frappe.db.get_value("Item Group", {lft: 1, is_group: 1}, "name");
+            this.parent_item_group = res.message.name;
+        };
+        if (!this.price_list) {
+            const res = await frappe.db.get_value("POS Profile", this.pos_profile, "selling_price_list");
+            this.price_list = res.message.selling_price_list;
+        }
+
+        this.get_items({}).then(({message}) => {
+            this.render_item_list(message.items);
+        });
+    }
+
+    get_items({start = 0, page_length = 40, search_value=''}) {
+        const price_list = this.events.get_frm().doc?.selling_price_list || this.price_list;
+        let { item_group, pos_profile } = this;
+
+        !item_group && (item_group = this.parent_item_group);
+        
+		return frappe.call({
+			method: "erpnext.selling.page.point_of_sale.point_of_sale.get_items",
+			freeze: true,
+            args: { start, page_length, price_list, item_group, search_value, pos_profile },
+        });
+	}
+
+
+	render_item_list(items) {
+        this.$items_container = this.$component.find('.items-container');
+        this.$items_container.html('');
+
+        items.forEach(item => {
+            const item_html = this.get_item_html(item);
+            this.$items_container.append(item_html);
+        })
+    }
+
+    get_item_html(item) {
+        const { item_image, serial_no, batch_no, barcode, actual_qty, stock_uom } = item;
+        const indicator_color = actual_qty > 10 ? "green" : actual_qty !== 0 ? "orange" : "red";
+
+        function get_item_image_html() {
+            if (item_image) {
+                return `<div class="flex items-center justify-center h-32 border-b-grey text-6xl text-grey-100">
+                            <img class="h-full" src="${item_image}" alt="${item_image}" style="object-fit: cover;">
+                        </div>`
+            } else {
+                return `<div class="flex items-center justify-center h-32 bg-light-grey text-6xl text-grey-100">
+                            ${frappe.get_abbr(item.item_name)}
+                        </div>`
+            }
+        }
+
+		return (
+            `<div class="item-wrapper rounded shadow pointer no-select" data-item-code="${escape(item.item_code)}"
+                data-serial-no="${escape(serial_no)}" data-batch-no="${escape(batch_no)}" data-uom="${escape(stock_uom)}"
+                title="Avaiable Qty: ${actual_qty}">
+                ${get_item_image_html()}
+                <div class="flex items-center pr-4 pl-4 h-10 justify-between">
+                    <div class="flex items-center f-shrink-1 text-dark-grey overflow-hidden whitespace-nowrap">
+                        <span class="indicator ${indicator_color}"></span>
+                        ${frappe.ellipsis(item.item_name, 18)}
+                    </div>
+                    <div class="f-shrink-0 text-dark-grey text-bold ml-4">${format_currency(item.price_list_rate, item.currency, 0) || 0}</div>
+                </div>
+            </div>`
+        )
+    }
+
+    make_search_bar() {
+        const me = this;
+        this.$component.find('.search-field').html('');
+        this.$component.find('.item-group-field').html('');
+
+		this.search_field = frappe.ui.form.make_control({
+			df: {
+				label: __('Search'),
+				fieldtype: 'Data',
+				placeholder: __('Search by item code, serial number, batch no or barcode')
+			},
+			parent: this.$component.find('.search-field'),
+			render_input: true,
+        });
+		this.item_group_field = frappe.ui.form.make_control({
+			df: {
+				label: __('Item Group'),
+				fieldtype: 'Link',
+				options: 'Item Group',
+                placeholder: __('Select item group'),
+                onchange: function() {
+                    me.item_group = this.value;
+                    !me.item_group && (me.item_group = me.parent_item_group);
+                    me.filter_items();
+                },
+                get_query: function () {
+                    return {
+                        query: 'erpnext.selling.page.point_of_sale.point_of_sale.item_group_query',
+                        filters: {
+                            pos_profile: me.events.get_frm().doc?.pos_profile
+                        }
+                    }
+                },
+			},
+            parent: this.$component.find('.item-group-field'),
+			render_input: true,
+        });
+        this.search_field.toggle_label(false);
+		this.item_group_field.toggle_label(false);
+	}
+
+    bind_events() {
+        const me = this;
+        onScan.attachTo(document, {
+            onScan: (sScancode) => {
+                if (this.search_field && this.$component.is(':visible')) {
+                    this.search_field.set_focus();
+                    $(this.search_field.$input[0]).val(sScancode).trigger("input");
+                    this.barcode_scanned = true;
+                }
+            }
+        });
+
+		this.$component.on('click', '.item-wrapper', function() {
+			const $item = $(this);
+			const item_code = unescape($item.attr('data-item-code'));
+            let batch_no = unescape($item.attr('data-batch-no'));
+            let serial_no = unescape($item.attr('data-serial-no'));
+            let uom = unescape($item.attr('data-uom'));
+            
+            // escape(undefined) returns "undefined" then unescape returns "undefined"
+            batch_no = batch_no === "undefined" ? undefined : batch_no;
+            serial_no = serial_no === "undefined" ? undefined : serial_no;
+            uom = uom === "undefined" ? undefined : uom;
+
+            me.events.item_selected({ field: 'qty', value: "+1", item: { item_code, batch_no, serial_no, uom }});
+        })
+
+        this.search_field.$input.on('input', (e) => {
+			clearTimeout(this.last_search);
+			this.last_search = setTimeout(() => {
+				const search_term = e.target.value;
+				this.filter_items({ search_term });
+			}, 300);
+        });
+    }
+
+    attach_shortcuts() {
+        frappe.ui.keys.on("ctrl+i", () => {
+            const selector_is_visible = this.$component.is(':visible');
+            if (!selector_is_visible) return;
+            this.search_field.set_focus();
+        });
+        frappe.ui.keys.on("ctrl+g", () => {
+            const selector_is_visible = this.$component.is(':visible');
+            if (!selector_is_visible) return;
+            this.item_group_field.set_focus();
+        });
+        // for selecting the last filtered item on search
+        frappe.ui.keys.on("enter", () => {
+            const selector_is_visible = this.$component.is(':visible');
+            if (!selector_is_visible || this.search_field.get_value() === "") return;
+
+            if (this.items.length == 1) {
+                this.$items_container.find(".item-wrapper").click();
+                frappe.utils.play_sound("submit");
+                $(this.search_field.$input[0]).val("").trigger("input");
+            } else if (this.items.length == 0 && this.barcode_scanned) {
+                // only show alert of barcode is scanned and enter is pressed
+                frappe.show_alert({
+                    message: __("No items found. Scan barcode again."),
+                    indicator: 'orange'
+                });
+                frappe.utils.play_sound("error");
+                this.barcode_scanned = false;
+                $(this.search_field.$input[0]).val("").trigger("input");
+            }
+        });
+    }
+    
+    filter_items({ search_term='' }={}) {
+		if (search_term) {
+			search_term = search_term.toLowerCase();
+
+			// memoize
+			this.search_index = this.search_index || {};
+			if (this.search_index[search_term]) {
+				const items = this.search_index[search_term];
+				this.items = items;
+				this.render_item_list(items);
+				return;
+            }
+		}
+
+		this.get_items({ search_value: search_term })
+            .then(({ message }) => {
+                const { items, serial_no, batch_no, barcode } = message;
+				if (search_term && !barcode) {
+					this.search_index[search_term] = items;
+				}
+				this.items = items;
+                this.render_item_list(items);
+            });
+	}
+    
+    resize_selector(minimize) {
+        minimize ? 
+        this.$component.find('.search-field').removeClass('mr-8') : 
+        this.$component.find('.search-field').addClass('mr-8');
+
+        minimize ? 
+        this.$component.find('.filter-section').addClass('flex-col') : 
+        this.$component.find('.filter-section').removeClass('flex-col');
+
+        minimize ?
+        this.$component.removeClass('col-span-6').addClass('col-span-2') :
+        this.$component.removeClass('col-span-2').addClass('col-span-6')
+
+        minimize ?
+        this.$items_container.removeClass('grid-cols-4').addClass('grid-cols-1') :
+        this.$items_container.removeClass('grid-cols-1').addClass('grid-cols-4')
+    }
+
+    toggle_component(show) {
+		show ? this.$component.removeClass('d-none') : this.$component.addClass('d-none');
+    }
+}
\ No newline at end of file
diff --git a/erpnext/selling/page/point_of_sale/pos_number_pad.js b/erpnext/selling/page/point_of_sale/pos_number_pad.js
new file mode 100644
index 0000000..2ffc2c0
--- /dev/null
+++ b/erpnext/selling/page/point_of_sale/pos_number_pad.js
@@ -0,0 +1,49 @@
+erpnext.PointOfSale.NumberPad = class {
+    constructor({ wrapper, events, cols, keys, css_classes, fieldnames_map }) {
+        this.wrapper = wrapper;
+        this.events = events;
+        this.cols = cols;
+        this.keys = keys;
+        this.css_classes = css_classes || [];
+        this.fieldnames = fieldnames_map || {};
+
+        this.init_component();
+    }
+
+    init_component() {
+        this.prepare_dom();
+        this.bind_events();
+    }
+
+    prepare_dom() {
+        const { cols, keys, css_classes, fieldnames } = this;
+
+        function get_keys() {
+           return keys.reduce((a, row, i) => {
+               return a + row.reduce((a2, number, j) => {
+                   const class_to_append = css_classes && css_classes[i] ? css_classes[i][j] : '';
+                   const fieldname = fieldnames && fieldnames[number] ? 
+                       fieldnames[number] : 
+                       typeof number === 'string' ? frappe.scrub(number) : number;
+                   
+                   return a2 + `<div class="numpad-btn pointer no-select rounded ${class_to_append}
+                                       flex items-center justify-center h-16 text-md border-grey border" data-button-value="${fieldname}">${number}</div>`
+               }, '')
+           }, '');
+       }
+
+        this.wrapper.html(
+            `<div class="grid grid-cols-${cols} gap-4">
+                ${get_keys()}
+           </div>`
+        )
+    }
+
+    bind_events() {
+       const me = this;
+       this.wrapper.on('click', '.numpad-btn', function() {
+           const $btn = $(this);
+           me.events.numpad_event($btn);
+       })
+    }
+}
\ No newline at end of file
diff --git a/erpnext/selling/page/point_of_sale/pos_past_order_list.js b/erpnext/selling/page/point_of_sale/pos_past_order_list.js
new file mode 100644
index 0000000..9181ee8
--- /dev/null
+++ b/erpnext/selling/page/point_of_sale/pos_past_order_list.js
@@ -0,0 +1,130 @@
+erpnext.PointOfSale.PastOrderList = class {
+    constructor({ wrapper, events }) {
+        this.wrapper = wrapper;
+        this.events = events;
+
+        this.init_component();
+    }
+
+    init_component() {
+        this.prepare_dom();
+        this.make_filter_section();
+        this.bind_events();
+    }
+
+    prepare_dom() {
+        this.wrapper.append(
+            `<section class="col-span-4 flex flex-col shadow rounded past-order-list bg-white mx-h-70 h-100 d-none">
+                <div class="flex flex-col rounded w-full scroll-y">
+                    <div class="filter-section flex flex-col p-8 pb-2 bg-white sticky z-100">
+                        <div class="search-field flex items-center text-grey"></div>
+                        <div class="status-field flex items-center text-grey text-bold"></div>
+                    </div>
+                    <div class="flex flex-1 flex-col p-8 pt-2">
+                        <div class="text-grey mb-6">RECENT ORDERS</div>
+                        <div class="invoices-container rounded border grid grid-cols-1"></div>					
+                    </div>
+                </div>
+            </section>`
+        )
+
+        this.$component = this.wrapper.find('.past-order-list');
+        this.$invoices_container = this.$component.find('.invoices-container');
+    }
+
+    bind_events() {
+        this.search_field.$input.on('input', (e) => {
+			clearTimeout(this.last_search);
+			this.last_search = setTimeout(() => {
+                const search_term = e.target.value;
+                this.refresh_list(search_term, this.status_field.get_value());
+			}, 300);
+        });
+        const me = this;
+        this.$invoices_container.on('click', '.invoice-wrapper', function() {
+            const invoice_name = unescape($(this).attr('data-invoice-name'));
+
+            me.events.open_invoice_data(invoice_name);
+        })
+    }
+
+    make_filter_section() {
+        const me = this;
+		this.search_field = frappe.ui.form.make_control({
+			df: {
+				label: __('Search'),
+				fieldtype: 'Data',
+				placeholder: __('Search by invoice id or customer name')
+			},
+			parent: this.$component.find('.search-field'),
+			render_input: true,
+        });
+		this.status_field = frappe.ui.form.make_control({
+			df: {
+				label: __('Invoice Status'),
+                fieldtype: 'Select',
+				options: `Draft\nPaid\nConsolidated\nReturn`,
+                placeholder: __('Filter by invoice status'),
+                onchange: function() {
+                    me.refresh_list(me.search_field.get_value(), this.value);
+                }
+			},
+            parent: this.$component.find('.status-field'),
+			render_input: true,
+        });
+        this.search_field.toggle_label(false);
+        this.status_field.toggle_label(false);
+        this.status_field.set_value('Paid');
+    }
+    
+    toggle_component(show) {
+        show ? 
+        this.$component.removeClass('d-none') && this.refresh_list() :
+        this.$component.addClass('d-none');
+    }
+
+    refresh_list() {
+        frappe.dom.freeze();
+        this.events.reset_summary();
+        const search_term = this.search_field.get_value();
+        const status = this.status_field.get_value();
+
+        this.$invoices_container.html('');
+
+        return frappe.call({
+			method: "erpnext.selling.page.point_of_sale.point_of_sale.get_past_order_list",
+			freeze: true,
+            args: { search_term, status },
+            callback: (response) => {
+                frappe.dom.unfreeze();
+                response.message.forEach(invoice => {
+                    const invoice_html = this.get_invoice_html(invoice);
+                    this.$invoices_container.append(invoice_html);
+                });
+            }
+       });
+    }
+
+    get_invoice_html(invoice) {
+        const posting_datetime = moment(invoice.posting_date+" "+invoice.posting_time).format("Do MMMM, h:mma");
+        return (
+            `<div class="invoice-wrapper flex p-4 justify-between border-b-grey pointer no-select" data-invoice-name="${escape(invoice.name)}">
+                <div class="flex flex-col justify-end">
+                    <div class="text-dark-grey text-bold overflow-hidden whitespace-nowrap mb-2">${invoice.name}</div>
+                    <div class="flex items-center">
+                        <div class="flex items-center f-shrink-1 text-dark-grey overflow-hidden whitespace-nowrap">
+                            <svg class="mr-2" width="12" height="12" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1" stroke-linecap="round" stroke-linejoin="round">
+                                <path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/>
+                            </svg>
+                            ${invoice.customer}
+                        </div>
+                    </div>
+                </div>
+                <div class="flex flex-col text-right">
+                    <div class="f-shrink-0 text-lg text-dark-grey text-bold ml-4">${format_currency(invoice.grand_total, invoice.currency, 0) || 0}</div>
+                    <div class="f-shrink-0 text-grey ml-4">${posting_datetime}</div>
+                </div>
+            </div>`
+        )
+    }
+}
\ No newline at end of file
diff --git a/erpnext/selling/page/point_of_sale/pos_past_order_summary.js b/erpnext/selling/page/point_of_sale/pos_past_order_summary.js
new file mode 100644
index 0000000..24326b2
--- /dev/null
+++ b/erpnext/selling/page/point_of_sale/pos_past_order_summary.js
@@ -0,0 +1,452 @@
+erpnext.PointOfSale.PastOrderSummary = class {
+    constructor({ wrapper, events }) {
+        this.wrapper = wrapper;
+        this.events = events;
+
+        this.init_component();
+    }
+
+    init_component() {
+        this.prepare_dom();
+        this.init_child_components();
+        this.bind_events();
+        this.attach_shortcuts();
+    }
+
+    prepare_dom() {
+        this.wrapper.append(
+            `<section class="col-span-6 flex flex-col items-center shadow rounded past-order-summary bg-white mx-h-70 h-100 d-none">
+                <div class="no-summary-placeholder flex flex-1 items-center justify-center p-16">
+                    <div class="no-item-wrapper flex items-center h-18 pr-4 pl-4">
+                        <div class="flex-1 text-center text-grey">Select an invoice to load summary data</div>
+                    </div>
+                </div>
+                <div class="summary-wrapper d-none flex-1 w-66 text-dark-grey relative">
+                    <div class="summary-container absolute flex flex-col pt-16 pb-16 pr-8 pl-8 w-full h-full"></div>
+                </div>
+            </section>`
+        )
+
+        this.$component = this.wrapper.find('.past-order-summary');
+        this.$summary_wrapper = this.$component.find('.summary-wrapper');
+        this.$summary_container = this.$component.find('.summary-container');
+    }
+
+    init_child_components() {
+        this.init_upper_section();
+        this.init_items_summary();
+        this.init_totals_summary();
+        this.init_payments_summary();
+        this.init_summary_buttons();
+        this.init_email_print_dialog();
+    }
+
+    init_upper_section() {
+        this.$summary_container.append(
+            `<div class="flex upper-section justify-between w-full h-24"></div>`
+        );
+
+        this.$upper_section = this.$summary_container.find('.upper-section');
+    }
+
+    init_items_summary() {
+        this.$summary_container.append(
+            `<div class="flex flex-col flex-1 mt-6 w-full scroll-y">
+                <div class="text-grey mb-4 sticky bg-white">ITEMS</div>
+                <div class="items-summary-container border rounded flex flex-col w-full"></div>
+            </div>`
+        )
+
+        this.$items_summary_container = this.$summary_container.find('.items-summary-container');
+    }
+
+    init_totals_summary() {
+        this.$summary_container.append(
+            `<div class="flex flex-col mt-6 w-full f-shrink-0">
+                <div class="text-grey mb-4">TOTALS</div>
+                <div class="summary-totals-container border rounded flex flex-col w-full"></div>
+            </div>`
+        )
+
+        this.$totals_summary_container = this.$summary_container.find('.summary-totals-container');
+    }
+
+    init_payments_summary() {
+        this.$summary_container.append(
+            `<div class="flex flex-col mt-6 w-full f-shrink-0">
+                <div class="text-grey mb-4">PAYMENTS</div>
+                <div class="payments-summary-container border rounded flex flex-col w-full mb-4"></div>
+            </div>`
+        )
+
+        this.$payment_summary_container = this.$summary_container.find('.payments-summary-container');
+    }
+
+    init_summary_buttons() {
+        this.$summary_container.append(
+            `<div class="summary-btns flex summary-btns justify-between w-full f-shrink-0"></div>`
+        )
+        
+        this.$summary_btns = this.$summary_container.find('.summary-btns');
+    }
+
+    init_email_print_dialog() {
+        const email_dialog = new frappe.ui.Dialog({
+            title: 'Email Receipt',
+            fields: [
+                {fieldname:'email_id', fieldtype:'Data', options: 'Email', label:'Email ID'},
+                // {fieldname:'remarks', fieldtype:'Text', label:'Remarks (if any)'}
+            ],
+            primary_action: () => {
+                this.send_email();
+            },
+            primary_action_label: __('Send'),
+        });
+        this.email_dialog = email_dialog;
+
+        const print_dialog = new frappe.ui.Dialog({
+            title: 'Print Receipt',
+            fields: [
+                {fieldname:'print', fieldtype:'Data', label:'Print Preview'}
+            ],
+            primary_action: () => {
+                this.events.get_frm().print_preview.printit(true);
+            },
+            primary_action_label: __('Print'),
+        });
+        this.print_dialog = print_dialog;
+    }
+
+    get_upper_section_html(doc) {
+        const { status } = doc; let indicator_color = '';
+
+        in_list(['Paid', 'Consolidated'], status) && (indicator_color = 'green');
+        status === 'Draft' && (indicator_color = 'red');
+        status === 'Return' && (indicator_color = 'grey');
+
+        return `<div class="flex flex-col items-start justify-end pr-4">
+                    <div class="text-lg text-bold pt-2">${doc.customer}</div>
+                    <div class="text-grey">${this.customer_email}</div>
+                    <div class="text-grey mt-auto">Sold by: ${doc.owner}</div>
+                </div>
+                <div class="flex flex-col flex-1 items-end justify-between">
+                    <div class="text-2-5xl text-bold">${format_currency(doc.paid_amount, doc.currency)}</div>
+                    <div class="flex justify-between">
+                        <div class="text-grey mr-4">${doc.name}</div>
+                        <div class="text-grey text-bold indicator ${indicator_color}">${doc.status}</div>
+                    </div>
+                </div>`
+    }
+
+    get_discount_html(doc) {
+        if (doc.discount_amount) {
+            return `<div class="total-summary-wrapper flex items-center h-12 pr-4 pl-4 pointer border-b-grey no-select">
+                    <div class="flex f-shrink-1 items-center">
+                        <div class="text-md-0 text-dark-grey text-bold overflow-hidden whitespace-nowrap  mr-2">
+                            Discount
+                        </div>
+                        <span class="text-grey">(${doc.additional_discount_percentage} %)</span>
+                    </div>
+                    <div class="flex flex-col f-shrink-0 ml-auto text-right">
+                        <div class="text-md-0 text-dark-grey text-bold">${format_currency(doc.discount_amount, doc.currency)}</div>
+                    </div>
+                </div>`;
+        } else {
+            return ``;
+        }
+    }
+
+    get_net_total_html(doc) {
+        return `<div class="total-summary-wrapper flex items-center h-12 pr-4 pl-4 pointer border-b-grey no-select">
+                    <div class="flex f-shrink-1 items-center">
+                        <div class="text-md-0 text-dark-grey text-bold overflow-hidden whitespace-nowrap">
+                            Net Total
+                        </div>
+                    </div>
+                    <div class="flex flex-col f-shrink-0 ml-auto text-right">
+                        <div class="text-md-0 text-dark-grey text-bold">${format_currency(doc.net_total, doc.currency)}</div>
+                    </div>
+                </div>`
+    }
+
+    get_taxes_html(doc) {
+        return `<div class="total-summary-wrapper flex items-center justify-between h-12 pr-4 pl-4 border-b-grey">
+                    <div class="flex">
+                        <div class="text-md-0 text-dark-grey text-bold w-fit">Tax Charges</div>
+                        <div class="flex ml-6 text-dark-grey">
+                        ${	
+                            doc.taxes.map((t, i) => {
+                                let margin_left = '';
+                                if (i !== 0) margin_left = 'ml-2';
+                                return `<span class="pl-2 pr-2 ${margin_left}">${t.description} @${t.rate}%</span>`
+                            }).join('')
+                        }
+                        </div>
+                    </div>
+                    <div class="flex flex-col text-right">
+                        <div class="text-md-0 text-dark-grey text-bold">${format_currency(doc.base_total_taxes_and_charges, doc.currency)}</div>
+                    </div>
+                </div>`
+    }
+
+    get_grand_total_html(doc) {
+        return `<div class="total-summary-wrapper flex items-center h-12 pr-4 pl-4 pointer border-b-grey no-select">
+                    <div class="flex f-shrink-1 items-center">
+                        <div class="text-md-0 text-dark-grey text-bold overflow-hidden whitespace-nowrap">
+                            Grand Total
+                        </div>
+                    </div>
+                    <div class="flex flex-col f-shrink-0 ml-auto text-right">
+                        <div class="text-md-0 text-dark-grey text-bold">${format_currency(doc.grand_total, doc.currency)}</div>
+                    </div>
+                </div>`
+    }
+
+    get_item_html(doc, item_data) {
+        return `<div class="item-summary-wrapper flex items-center h-12 pr-4 pl-4 border-b-grey pointer no-select">
+                    <div class="flex w-6 h-6 rounded bg-light-grey mr-4 items-center justify-center font-bold f-shrink-0">
+                        <span>${item_data.qty || 0}</span>
+                    </div>
+                    <div class="flex flex-col f-shrink-1">
+                        <div class="text-md text-dark-grey text-bold overflow-hidden whitespace-nowrap">
+                            ${item_data.item_name}
+                        </div>
+                    </div>
+                    <div class="flex f-shrink-0 ml-auto text-right">
+                        ${get_rate_discount_html()}
+                    </div>
+                </div>`
+
+        function get_rate_discount_html() {
+            if (item_data.rate && item_data.price_list_rate && item_data.rate !== item_data.price_list_rate) {
+                return `<span class="text-grey mr-2">(${item_data.discount_percentage}% off)</span>
+                        <div class="text-md-0 text-dark-grey text-bold">${format_currency(item_data.rate, doc.currency)}</div>`
+            } else {
+                return `<div class="text-md-0 text-dark-grey text-bold">${format_currency(item_data.price_list_rate || item_data.rate, doc.currency)}</div>`
+            }
+        }
+    }
+
+    get_payment_html(doc, payment) {
+        return `<div class="payment-summary-wrapper flex items-center h-12 pr-4 pl-4 pointer border-b-grey no-select">
+                    <div class="flex f-shrink-1 items-center">
+                        <div class="text-md-0 text-dark-grey text-bold overflow-hidden whitespace-nowrap">
+                            ${payment.mode_of_payment}
+                        </div>
+                    </div>
+                    <div class="flex flex-col f-shrink-0 ml-auto text-right">
+                        <div class="text-md-0 text-dark-grey text-bold">${format_currency(payment.amount, doc.currency)}</div>
+                    </div>
+                </div>`
+    }
+
+    bind_events() {
+        this.$summary_container.on('click', '.return-btn', () => {
+            this.events.process_return(this.doc.name);
+            this.toggle_component(false);
+            this.$component.find('.no-summary-placeholder').removeClass('d-none');
+            this.$summary_wrapper.addClass('d-none');
+        });
+
+        this.$summary_container.on('click', '.edit-btn', () => {
+            this.events.edit_order(this.doc.name);
+            this.toggle_component(false);
+            this.$component.find('.no-summary-placeholder').removeClass('d-none');
+            this.$summary_wrapper.addClass('d-none');
+        });
+
+        this.$summary_container.on('click', '.new-btn', () => {
+            this.events.new_order();
+            this.toggle_component(false);
+            this.$component.find('.no-summary-placeholder').removeClass('d-none');
+            this.$summary_wrapper.addClass('d-none');
+        });
+
+        this.$summary_container.on('click', '.email-btn', () => {
+            this.email_dialog.fields_dict.email_id.set_value(this.customer_email);
+            this.email_dialog.show();
+        });
+
+        this.$summary_container.on('click', '.print-btn', () => {
+            // this.print_dialog.show();
+            const frm = this.events.get_frm();
+            frm.doc = this.doc;
+            frm.print_preview.printit(true);
+        });
+    }
+
+    attach_shortcuts() {
+        frappe.ui.keys.on("ctrl+p", () => {
+            const print_btn_visible = this.$summary_container.find('.print-btn').is(":visible");
+            const summary_visible = this.$component.is(":visible");
+            if (!summary_visible || !print_btn_visible) return;
+
+            this.$summary_container.find('.print-btn').click();
+        });
+    }
+    
+    toggle_component(show) {
+        show ? 
+        this.$component.removeClass('d-none') :
+        this.$component.addClass('d-none');
+    }
+
+    send_email() {
+        const frm = this.events.get_frm();
+        const recipients = this.email_dialog.get_values().recipients;
+        const doc = this.doc || frm.doc;
+        const print_format = frm.pos_print_format;
+
+        frappe.call({
+            method:"frappe.core.doctype.communication.email.make",
+            args: {
+                recipients: recipients,
+                subject: __(frm.meta.name) + ': ' + doc.name,
+                doctype: doc.doctype,
+                name: doc.name,
+                send_email: 1,
+                print_format,
+                sender_full_name: frappe.user.full_name(),
+                _lang : doc.language
+            },
+            callback: r => {
+                if(!r.exc) {
+                    frappe.utils.play_sound("email");
+                    if(r.message["emails_not_sent_to"]) {
+                        frappe.msgprint(__("Email not sent to {0} (unsubscribed / disabled)",
+                            [ frappe.utils.escape_html(r.message["emails_not_sent_to"]) ]) );
+                    } else {
+                        frappe.show_alert({
+                            message: __('Email sent successfully.'),
+                            indicator: 'green'
+                        });
+                    }
+                    this.email_dialog.hide();
+                } else {
+                    frappe.msgprint(__("There were errors while sending email. Please try again."));
+                }
+            }
+        });
+    }
+
+    add_summary_btns(map) {
+        this.$summary_btns.html('');
+        map.forEach(m => {
+            if (m.condition) {
+                m.visible_btns.forEach(b => {
+                    const class_name = b.split(' ')[0].toLowerCase();
+                    this.$summary_btns.append(
+                        `<div class="${class_name}-btn border rounded h-14 flex flex-1 items-center mr-4 justify-center text-md text-bold no-select pointer">
+                            ${b}
+                        </div>`
+                    )
+                });
+            }
+        });
+        this.$summary_btns.children().last().removeClass('mr-4');
+    }
+
+    show_summary_placeholder() {
+        this.$summary_wrapper.addClass("d-none");
+        this.$component.find('.no-summary-placeholder').removeClass('d-none');
+    }
+
+    switch_to_post_submit_summary() {
+        // switch to full width view
+        this.$component.removeClass('col-span-6').addClass('col-span-10');
+        this.$summary_wrapper.removeClass('w-66').addClass('w-40');
+
+        // switch place holder with summary container
+        this.$component.find('.no-summary-placeholder').addClass('d-none');
+        this.$summary_wrapper.removeClass('d-none');
+    }
+
+    switch_to_recent_invoice_summary() {
+        // switch full width view with 60% view
+        this.$component.removeClass('col-span-10').addClass('col-span-6');
+        this.$summary_wrapper.removeClass('w-40').addClass('w-66');
+
+        // switch place holder with summary container
+        this.$component.find('.no-summary-placeholder').addClass('d-none');
+        this.$summary_wrapper.removeClass('d-none');
+    }
+
+    get_condition_btn_map(after_submission) {
+        if (after_submission) 
+            return [{ condition: true, visible_btns: ['Print Receipt', 'Email Receipt', 'New Order'] }];
+        
+        return [
+            { condition: this.doc.docstatus === 0, visible_btns: ['Edit Order'] },
+            { condition: !this.doc.is_return && this.doc.docstatus === 1, visible_btns: ['Print Receipt', 'Email Receipt', 'Return']},
+            { condition: this.doc.is_return && this.doc.docstatus === 1, visible_btns: ['Print Receipt', 'Email Receipt']}
+        ];
+    }
+
+    load_summary_of(doc, after_submission=false) {
+        this.$summary_wrapper.removeClass("d-none");
+        
+        after_submission ?
+            this.switch_to_post_submit_summary() : this.switch_to_recent_invoice_summary();
+
+        this.doc = doc;
+
+        this.attach_basic_info(doc);
+
+        this.attach_items_info(doc);
+
+        this.attach_totals_info(doc);
+
+        this.attach_payments_info(doc);
+
+        const condition_btns_map = this.get_condition_btn_map(after_submission);
+
+        this.add_summary_btns(condition_btns_map);
+    }
+
+    attach_basic_info(doc) {
+        frappe.db.get_value('Customer', this.doc.customer, 'email_id').then(({ message }) => {
+            this.customer_email = message.email_id || '';
+            const upper_section_dom = this.get_upper_section_html(doc);
+            this.$upper_section.html(upper_section_dom);
+        });
+    }
+
+    attach_items_info(doc) {
+        this.$items_summary_container.html('');
+        doc.items.forEach(item => {
+            const item_dom = this.get_item_html(doc, item);
+            this.$items_summary_container.append(item_dom);
+        });
+    }
+
+    attach_payments_info(doc) {
+        this.$payment_summary_container.html('');
+        doc.payments.forEach(p => {
+            if (p.amount) {
+                const payment_dom = this.get_payment_html(doc, p);
+                this.$payment_summary_container.append(payment_dom);
+            }
+        });
+        if (doc.redeem_loyalty_points && doc.loyalty_amount) {
+            const payment_dom = this.get_payment_html(doc, {
+                mode_of_payment: 'Loyalty Points',
+                amount: doc.loyalty_amount,
+            });
+            this.$payment_summary_container.append(payment_dom);
+        }
+    }
+
+    attach_totals_info(doc) {
+        this.$totals_summary_container.html('');
+
+        const discount_dom = this.get_discount_html(doc);
+        const net_total_dom = this.get_net_total_html(doc);
+        const taxes_dom = this.get_taxes_html(doc);
+        const grand_total_dom = this.get_grand_total_html(doc);
+        this.$totals_summary_container.append(discount_dom);
+        this.$totals_summary_container.append(net_total_dom);
+        this.$totals_summary_container.append(taxes_dom);
+        this.$totals_summary_container.append(grand_total_dom);
+    }
+
+}
\ No newline at end of file
diff --git a/erpnext/selling/page/point_of_sale/pos_payment.js b/erpnext/selling/page/point_of_sale/pos_payment.js
new file mode 100644
index 0000000..e1c54f6
--- /dev/null
+++ b/erpnext/selling/page/point_of_sale/pos_payment.js
@@ -0,0 +1,503 @@
+{% include "erpnext/selling/page/point_of_sale/pos_number_pad.js" %}
+
+erpnext.PointOfSale.Payment = class {
+	constructor({ events, wrapper }) {
+		this.wrapper = wrapper;
+		this.events = events;
+
+		this.init_component();
+	}
+
+	init_component() {
+        this.prepare_dom();
+        this.initialize_numpad();
+		this.bind_events();
+		this.attach_shortcuts();
+		
+	}
+
+	prepare_dom() {
+		this.wrapper.append(
+            `<section class="col-span-6 flex shadow rounded payment-section bg-white mx-h-70 h-100 d-none">
+				<div class="flex flex-col p-16 pt-8 pb-8 w-full">
+					<div class="text-grey mb-6 payment-section no-select pointer">
+						PAYMENT METHOD<span class="octicon octicon-chevron-down collapse-indicator"></span>
+					</div>
+					<div class="payment-modes flex flex-wrap"></div>
+					<div class="invoice-details-section"></div>
+                    <div class="flex mt-auto justify-center w-full">
+                        <div class="flex flex-col justify-center flex-1 ml-4">
+                            <div class="flex w-full">
+                                <div class="totals-remarks items-end justify-end flex flex-1">
+                                    <div class="remarks text-md-0 text-grey mr-auto"></div>
+                                    <div class="totals flex justify-end pt-4"></div>
+                                </div>
+                                <div class="number-pad w-40 mb-4 ml-8 d-none"></div>
+                            </div>
+                            <div class="flex items-center justify-center mt-4 submit-order h-16 w-full rounded bg-primary text-md text-white no-select pointer text-bold">
+                                Complete Order
+							</div>
+							<div class="order-time flex items-center justify-end mt-2 pt-2 pb-2 w-full text-md-0 text-grey no-select pointer d-none"></div>
+                        </div>
+                    </div>
+                </div>
+            </section>`
+        )
+        this.$component = this.wrapper.find('.payment-section');
+		this.$payment_modes = this.$component.find('.payment-modes');
+		this.$totals_remarks = this.$component.find('.totals-remarks');
+		this.$totals = this.$component.find('.totals');
+		this.$remarks = this.$component.find('.remarks');
+		this.$numpad = this.$component.find('.number-pad');
+		this.$invoice_details_section = this.$component.find('.invoice-details-section');
+	}
+
+	make_invoice_fields_control() {
+		frappe.db.get_doc("POS Settings", undefined).then((doc) => {
+			const fields = doc.invoice_fields;
+			if (!fields.length) return;
+
+			this.$invoice_details_section.html(
+				`<div class="text-grey pb-6 mt-2 pointer no-select">
+					ADDITIONAL INFORMATION<span class="octicon octicon-chevron-down collapse-indicator"></span>
+				</div>
+				<div class="invoice-fields grid grid-cols-2 gap-4 mb-6 d-none"></div>`
+			);
+			this.$invoice_fields = this.$invoice_details_section.find('.invoice-fields');
+			const frm = this.events.get_frm();
+
+			fields.forEach(df => {
+				this.$invoice_fields.append(
+					`<div class="invoice_detail_field ${df.fieldname}-field" data-fieldname="${df.fieldname}"></div>`
+				);
+
+				this[`${df.fieldname}_field`] = frappe.ui.form.make_control({
+					df: { 
+						...df,
+						onchange: function() {
+							frm.set_value(this.df.fieldname, this.value);
+						}
+					},
+					parent: this.$invoice_fields.find(`.${df.fieldname}-field`),
+					render_input: true,
+				});
+				this[`${df.fieldname}_field`].set_value(frm.doc[df.fieldname]);
+			})
+		});
+	}
+
+	initialize_numpad() {
+		const me = this;
+		this.number_pad = new erpnext.PointOfSale.NumberPad({
+			wrapper: this.$numpad,
+			events: {
+				numpad_event: function($btn) {
+					me.on_numpad_clicked($btn);
+				}
+			},
+			cols: 3,
+			keys: [
+				[ 1, 2, 3 ],
+				[ 4, 5, 6 ],
+				[ 7, 8, 9 ],
+				[ '.', 0, 'Delete' ]
+			],
+		})
+
+		this.numpad_value = '';
+	}
+
+	on_numpad_clicked($btn) {
+		const me = this;
+		const button_value = $btn.attr('data-button-value');
+
+		highlight_numpad_btn($btn);
+		this.numpad_value = button_value === 'delete' ? this.numpad_value.slice(0, -1) : this.numpad_value + button_value;
+		this.selected_mode.$input.get(0).focus();
+		this.selected_mode.set_value(this.numpad_value);
+
+		function highlight_numpad_btn($btn) {
+			$btn.addClass('shadow-inner bg-selected');
+			setTimeout(() => {
+				$btn.removeClass('shadow-inner bg-selected');
+			}, 100);
+		}
+	}
+
+	bind_events() {
+		const me = this;
+
+		this.$payment_modes.on('click', '.mode-of-payment', function(e) {
+			const mode_clicked = $(this);
+			// if clicked element doesn't have .mode-of-payment class then return
+			if (!$(e.target).is(mode_clicked)) return;
+
+			const mode = mode_clicked.attr('data-mode');
+
+			// hide all control fields and shortcuts
+			$(`.mode-of-payment-control`).addClass('d-none');
+			$(`.cash-shortcuts`).addClass('d-none');
+			me.$payment_modes.find(`.pay-amount`).removeClass('d-none');
+			me.$payment_modes.find(`.loyalty-amount-name`).addClass('d-none');
+
+			// remove highlight from all mode-of-payments
+			$('.mode-of-payment').removeClass('border-primary');
+
+			if (mode_clicked.hasClass('border-primary')) {
+				// clicked one is selected then unselect it
+				mode_clicked.removeClass('border-primary');
+				me.selected_mode = '';
+				me.toggle_numpad(false);
+			} else {
+				// clicked one is not selected then select it
+				mode_clicked.addClass('border-primary');
+				mode_clicked.find('.mode-of-payment-control').removeClass('d-none');
+				mode_clicked.find('.cash-shortcuts').removeClass('d-none');
+				me.$payment_modes.find(`.${mode}-amount`).addClass('d-none');
+				me.$payment_modes.find(`.${mode}-name`).removeClass('d-none');
+				me.toggle_numpad(true);
+
+				me.selected_mode = me[`${mode}_control`];
+				const doc = me.events.get_frm().doc;
+				me.selected_mode?.$input?.get(0).focus();
+				!me.selected_mode?.get_value() ? me.selected_mode?.set_value(doc.grand_total - doc.paid_amount) : '';
+			}
+		})
+
+		this.$payment_modes.on('click', '.shortcut', function(e) {
+			const value = $(this).attr('data-value');
+			me.selected_mode.set_value(value);
+		})
+
+		// this.$totals_remarks.on('click', '.remarks', () => {
+		// 	this.toggle_remarks_control();
+		// })
+
+		this.$component.on('click', '.submit-order', () => {
+			const doc = this.events.get_frm().doc;
+			const paid_amount = doc.paid_amount;
+			const items = doc.items;
+
+			if (paid_amount == 0 || !items.length) {
+				const message = items.length ? __("You cannot submit the order without payment.") : __("You cannot submit empty order.")
+				frappe.show_alert({ message, indicator: "orange" });
+				frappe.utils.play_sound("error");
+				return;
+			}
+
+			this.events.submit_invoice();
+		})
+
+		frappe.ui.form.on('POS Invoice', 'paid_amount', (frm) => {
+			this.update_totals_section(frm.doc);
+
+			// need to re calculate cash shortcuts after discount is applied
+			const is_cash_shortcuts_invisible = this.$payment_modes.find('.cash-shortcuts').hasClass('d-none');
+			this.attach_cash_shortcuts(frm.doc);
+			!is_cash_shortcuts_invisible && this.$payment_modes.find('.cash-shortcuts').removeClass('d-none');
+		})
+
+		frappe.ui.form.on('POS Invoice', 'loyalty_amount', (frm) => {
+			const formatted_currency = format_currency(frm.doc.loyalty_amount, frm.doc.currency);
+			this.$payment_modes.find(`.loyalty-amount-amount`).html(formatted_currency);
+		});
+
+		frappe.ui.form.on("Sales Invoice Payment", "amount", (frm, cdt, cdn) => {
+			// for setting correct amount after loyalty points are redeemed
+			const default_mop = locals[cdt][cdn];
+			const mode = default_mop.mode_of_payment.replace(' ', '_').toLowerCase();
+			if (this[`${mode}_control`] && this[`${mode}_control`].get_value() != default_mop.amount) {
+				this[`${mode}_control`].set_value(default_mop.amount);
+			}
+		});
+
+		this.$component.on('click', '.invoice-details-section', function(e) {
+			if ($(e.target).closest('.invoice-fields').length) return;
+
+			me.$payment_modes.addClass('d-none');
+			me.$invoice_fields.toggleClass("d-none");
+			me.toggle_numpad(false);
+		});
+		this.$component.on('click', '.payment-section', () => {
+			this.$invoice_fields.addClass("d-none");
+			this.$payment_modes.toggleClass('d-none');
+			this.toggle_numpad(true);
+		})
+	}
+
+	attach_shortcuts() {
+		frappe.ui.keys.on("ctrl+enter", () => {
+			const payment_is_visible = this.$component.is(":visible");
+			const active_mode = this.$payment_modes.find(".border-primary");
+			if (payment_is_visible && active_mode.length) {
+				this.$component.find('.submit-order').click();
+			}
+		});
+
+		frappe.ui.keys.on("tab", () => {
+			const payment_is_visible = this.$component.is(":visible");
+			const mode_of_payments = Array.from(this.$payment_modes.find(".mode-of-payment")).map(m => $(m).attr("data-mode"));
+			let active_mode = this.$payment_modes.find(".border-primary");
+			active_mode = active_mode.length ? active_mode.attr("data-mode") : undefined;
+
+			if (!active_mode) return;
+
+			const mode_index = mode_of_payments.indexOf(active_mode);
+			const next_mode_index = (mode_index + 1) % mode_of_payments.length;
+			const next_mode_to_be_clicked = this.$payment_modes.find(`.mode-of-payment[data-mode="${mode_of_payments[next_mode_index]}"]`);
+
+			if (payment_is_visible && mode_index != next_mode_index) {
+				next_mode_to_be_clicked.click();
+			}
+		});
+	}
+
+	toggle_numpad(show) {
+		if (show) {
+			this.$numpad.removeClass('d-none');
+			this.$remarks.addClass('d-none');
+			this.$totals_remarks.addClass('w-60 justify-center').removeClass('justify-end w-full');
+		} else {
+			this.$numpad.addClass('d-none');
+			this.$remarks.removeClass('d-none');
+			this.$totals_remarks.removeClass('w-60 justify-center').addClass('justify-end w-full');
+		}
+	}
+
+	render_payment_section() {
+		this.render_payment_mode_dom();
+		this.make_invoice_fields_control();
+		this.update_totals_section();
+	}
+
+	edit_cart() {
+		this.events.toggle_other_sections(false);
+		this.toggle_component(false);
+	}
+
+	checkout() {
+		this.events.toggle_other_sections(true);
+		this.toggle_component(true);
+
+		this.render_payment_section();
+	}
+
+	toggle_remarks_control() {
+		if (this.$remarks.find('.frappe-control').length) {
+			this.$remarks.html('+ Add Remark');
+		} else {
+			this.$remarks.html('');
+			this[`remark_control`] = frappe.ui.form.make_control({
+				df: {
+					label: __('Remark'),
+					fieldtype: 'Data',
+					onchange: function() {}
+				},
+				parent: this.$totals_remarks.find(`.remarks`),
+				render_input: true,
+			});
+			this[`remark_control`].set_value('');
+		}
+	}
+
+	render_payment_mode_dom() {
+		const doc = this.events.get_frm().doc;
+		const payments = doc.payments;
+		const currency = doc.currency;
+
+		this.$payment_modes.html(
+		   `${
+			   payments.map((p, i) => {
+				const mode = p.mode_of_payment.replace(' ', '_').toLowerCase();
+				const payment_type = p.type;
+				const margin = i % 2 === 0 ? 'pr-2' : 'pl-2';
+				const amount = p.amount > 0 ? format_currency(p.amount, currency) : '';
+
+				return (
+					`<div class="w-half ${margin} bg-white">
+						<div class="mode-of-payment rounded border border-grey text-grey text-md
+								mb-4 p-8 pt-4 pb-4 no-select pointer" data-mode="${mode}" data-payment-type="${payment_type}">
+							${p.mode_of_payment}
+							<div class="${mode}-amount pay-amount inline float-right text-bold">${amount}</div>
+							<div class="${mode} mode-of-payment-control mt-4 flex flex-1 items-center d-none"></div>
+						</div>
+					</div>`
+				)
+			   }).join('')
+		   }`
+		)
+
+		payments.forEach(p => {
+			const mode = p.mode_of_payment.replace(' ', '_').toLowerCase();
+			const me = this;
+			this[`${mode}_control`] = frappe.ui.form.make_control({
+				df: {
+					label: __(`${p.mode_of_payment}`),
+					fieldtype: 'Currency',
+					placeholder: __(`Enter ${p.mode_of_payment} amount.`),
+					onchange: function() {
+						if (this.value || this.value == 0) {
+							frappe.model.set_value(p.doctype, p.name, 'amount', flt(this.value))
+								.then(() => me.update_totals_section());
+
+							const formatted_currency = format_currency(this.value, currency);
+							me.$payment_modes.find(`.${mode}-amount`).html(formatted_currency);
+						}
+					}
+				},
+				parent: this.$payment_modes.find(`.${mode}.mode-of-payment-control`),
+				render_input: true,
+			});
+			this[`${mode}_control`].toggle_label(false);
+			this[`${mode}_control`].set_value(p.amount);
+
+			if (p.default) {
+				setTimeout(() => {
+					this.$payment_modes.find(`.${mode}.mode-of-payment-control`).parent().click();
+				}, 500);
+			}
+		})
+
+		this.render_loyalty_points_payment_mode();
+		
+		this.attach_cash_shortcuts(doc);
+	}
+
+	attach_cash_shortcuts(doc) {
+		const grand_total = doc.grand_total;
+		const currency = doc.currency;
+
+		const shortcuts = this.get_cash_shortcuts(flt(grand_total));
+
+		this.$payment_modes.find('.cash-shortcuts').remove();
+		this.$payment_modes.find('[data-payment-type="Cash"]').find('.mode-of-payment-control').after(
+			`<div class="cash-shortcuts grid grid-cols-3 gap-2 flex-1 text-center text-md-0 mb-2 d-none">
+				${
+					shortcuts.map(s => {
+						return `<div class="shortcut rounded bg-light-grey text-dark-grey pt-2 pb-2 no-select pointer" data-value="${s}">
+									${format_currency(s, currency)}
+								</div>`
+					}).join('')
+				}
+			</div>`
+		)
+	}
+
+	get_cash_shortcuts(grand_total) {
+		let steps = [1, 5, 10];
+		const digits = String(Math.round(grand_total)).length;
+
+		steps = steps.map(x => x * (10 ** (digits - 2)));
+
+		const get_nearest = (amount, x) => {
+			let nearest_x = Math.ceil((amount / x)) * x;
+			return nearest_x === amount ? nearest_x + x : nearest_x;
+		}
+
+		return steps.reduce((finalArr, x) => {
+			let nearest_x = get_nearest(grand_total, x);
+			nearest_x = finalArr.indexOf(nearest_x) != -1 ? nearest_x + x : nearest_x;
+			return [...finalArr, nearest_x];
+		}, []);	
+	}
+
+	render_loyalty_points_payment_mode() {
+		const me = this;
+		const doc = this.events.get_frm().doc;
+		const { loyalty_program, loyalty_points, conversion_factor } = this.events.get_customer_details();
+
+		this.$payment_modes.find(`.mode-of-payment[data-mode="loyalty-amount"]`).parent().remove();
+		
+		if (!loyalty_program) return;
+
+		let description, read_only, max_redeemable_amount;
+		if (!loyalty_points) {
+			description = __(`You don't have enough points to redeem.`);
+			read_only = true;
+		} else {
+			max_redeemable_amount = flt(flt(loyalty_points) * flt(conversion_factor), precision("loyalty_amount", doc))
+			description = __(`You can redeem upto ${format_currency(max_redeemable_amount)}.`);
+			read_only = false;
+		}
+
+		const margin = this.$payment_modes.children().length % 2 === 0 ? 'pr-2' : 'pl-2';
+		const amount = doc.loyalty_amount > 0 ? format_currency(doc.loyalty_amount, doc.currency) : '';
+		this.$payment_modes.append(
+			`<div class="w-half ${margin} bg-white">
+				<div class="mode-of-payment rounded border border-grey text-grey text-md
+						mb-4 p-8 pt-4 pb-4 no-select pointer" data-mode="loyalty-amount" data-payment-type="loyalty-amount">
+					Redeem Loyalty Points
+					<div class="loyalty-amount-amount pay-amount inline float-right text-bold">${amount}</div>
+					<div class="loyalty-amount-name inline float-right text-bold text-md-0 d-none">${loyalty_program}</div>
+					<div class="loyalty-amount mode-of-payment-control mt-4 flex flex-1 items-center d-none"></div>
+				</div>
+			</div>`
+		)
+
+		this['loyalty-amount_control'] = frappe.ui.form.make_control({
+			df: {
+				label: __('Redeem Loyalty Points'),
+				fieldtype: 'Currency',
+				placeholder: __(`Enter amount to be redeemed.`),
+				options: 'company:currency',
+				read_only,
+				onchange: async function() {
+					if (!loyalty_points) return;
+
+					if (this.value > max_redeemable_amount) {
+						frappe.show_alert({
+							message: __(`You cannot redeem more than ${format_currency(max_redeemable_amount)}.`),
+							indicator: "red"
+						});
+						frappe.utils.play_sound("submit");
+						me['loyalty-amount_control'].set_value(0);
+						return;
+					}
+					const redeem_loyalty_points = this.value > 0 ? 1 : 0;
+					await frappe.model.set_value(doc.doctype, doc.name, 'redeem_loyalty_points', redeem_loyalty_points);
+					frappe.model.set_value(doc.doctype, doc.name, 'loyalty_points', parseInt(this.value / conversion_factor));
+				},
+				description
+			},
+			parent: this.$payment_modes.find(`.loyalty-amount.mode-of-payment-control`),
+			render_input: true,
+		});
+		this['loyalty-amount_control'].toggle_label(false);
+
+		// this.render_add_payment_method_dom();
+	}
+
+	render_add_payment_method_dom() {
+		const docstatus = this.events.get_frm().doc.docstatus;
+		if (docstatus === 0)
+			this.$payment_modes.append(
+				`<div class="w-full pr-2">
+					<div class="add-mode-of-payment w-half text-grey mb-4 no-select pointer">+ Add Payment Method</div>
+				</div>`
+			)
+	}
+
+	update_totals_section(doc) {
+		if (!doc) doc = this.events.get_frm().doc;
+		const paid_amount = doc.paid_amount;
+		const remaining = doc.grand_total - doc.paid_amount;
+		const change = doc.change_amount || remaining <= 0 ? -1 * remaining : undefined;
+		const currency = doc.currency
+		const label = change ? __('Change') : __('To Be Paid');
+
+		this.$totals.html(
+			`<div>
+				<div class="pr-8 border-r-grey">Paid Amount</div>
+				<div class="pr-8 border-r-grey text-bold text-2xl">${format_currency(paid_amount, currency)}</div>
+			</div>
+			<div>
+				<div class="pl-8">${label}</div>
+				<div class="pl-8 text-green-400 text-bold text-2xl">${format_currency(change || remaining, currency)}</div>
+			</div>`
+		)
+	}
+
+	toggle_component(show) {
+		show ? this.$component.removeClass('d-none') : this.$component.addClass('d-none');
+    }
+ }
\ No newline at end of file
diff --git a/erpnext/selling/page/point_of_sale/tests/test_point_of_sale.js b/erpnext/selling/page/point_of_sale/tests/test_point_of_sale.js
deleted file mode 100644
index 79d1700..0000000
--- a/erpnext/selling/page/point_of_sale/tests/test_point_of_sale.js
+++ /dev/null
@@ -1,38 +0,0 @@
-QUnit.test("test:Point of Sales", function(assert) {
-	assert.expect(1);
-	let done = assert.async();
-
-	frappe.run_serially([
-		() => frappe.set_route('point-of-sale'),
-		() => frappe.timeout(3),
-		() => frappe.set_control('customer', 'Test Customer 1'),
-		() => frappe.timeout(0.2),
-		() => cur_frm.set_value('customer', 'Test Customer 1'),
-		() => frappe.timeout(2),
-		() => frappe.click_link('Test Product 2'),
-		() => frappe.timeout(0.2),
-		() => frappe.click_element(`.cart-items [data-item-code="Test Product 2"]`),
-		() => frappe.timeout(0.2),
-		() => frappe.click_element(`.number-pad [data-value="Rate"]`),
-		() => frappe.timeout(0.2),
-		() => frappe.click_element(`.number-pad [data-value="2"]`),
-		() => frappe.timeout(0.2),
-		() => frappe.click_element(`.number-pad [data-value="5"]`),
-		() => frappe.timeout(0.2),
-		() => frappe.click_element(`.number-pad [data-value="0"]`),
-		() => frappe.timeout(0.2),
-		() => frappe.click_element(`.number-pad [data-value="Pay"]`),
-		() => frappe.timeout(0.2),
-		() => frappe.click_element(`.frappe-control [data-value="4"]`),
-		() => frappe.timeout(0.2),
-		() => frappe.click_element(`.frappe-control [data-value="5"]`),
-		() => frappe.timeout(0.2),
-		() => frappe.click_element(`.frappe-control [data-value="0"]`),
-		() => frappe.timeout(0.2),
-		() => frappe.click_button('Submit'),
-		() => frappe.click_button('Yes'),
-		() => frappe.timeout(3),
-		() => assert.ok(cur_frm.doc.docstatus==1, "Sales invoice created successfully"),
-		() => done()
-	]);
-});
\ No newline at end of file
diff --git a/erpnext/selling/doctype/pos_closing_voucher/__init__.py b/erpnext/selling/print_format/__init__.py
similarity index 100%
rename from erpnext/selling/doctype/pos_closing_voucher/__init__.py
rename to erpnext/selling/print_format/__init__.py
diff --git a/erpnext/selling/doctype/pos_closing_voucher/__init__.py b/erpnext/selling/print_format/gst_pos_invoice/__init__.py
similarity index 100%
copy from erpnext/selling/doctype/pos_closing_voucher/__init__.py
copy to erpnext/selling/print_format/gst_pos_invoice/__init__.py
diff --git a/erpnext/selling/print_format/gst_pos_invoice/gst_pos_invoice.json b/erpnext/selling/print_format/gst_pos_invoice/gst_pos_invoice.json
new file mode 100644
index 0000000..9094a07b
--- /dev/null
+++ b/erpnext/selling/print_format/gst_pos_invoice/gst_pos_invoice.json
@@ -0,0 +1,23 @@
+{
+ "align_labels_right": 0,
+ "creation": "2017-08-08 12:33:04.773099",
+ "custom_format": 1,
+ "disabled": 0,
+ "doc_type": "POS Invoice",
+ "docstatus": 0,
+ "doctype": "Print Format",
+ "font": "Default",
+ "html": "<style>\n\t.print-format table, .print-format tr, \n\t.print-format td, .print-format div, .print-format p {\n\t\tfont-family: Tahoma, sans-serif;\n\t\tline-height: 150%;\n\t\tvertical-align: middle;\n\t}\n\t@media screen {\n\t\t.print-format {\n\t\t\twidth: 4in;\n\t\t\tpadding: 0.25in;\n\t\t\tmin-height: 8in;\n\t\t}\n\t}\n</style>\n\n{% if letter_head %}\n    {{ letter_head }}\n{% endif %}\n<p class=\"text-center\">\n\t{{ doc.company }}<br>\n\t{% if doc.company_address_display %}\n\t\t{% set company_address = doc.company_address_display.replace(\"\\n\", \" \").replace(\"<br>\", \" \") %}\n\t\t{% if \"GSTIN\" not in company_address %}\n\t\t\t{{ company_address }}\n\t\t\t<b>{{ _(\"GSTIN\") }}:</b>{{ doc.company_gstin }}\n\t\t{% else %}\n\t\t\t{{ company_address.replace(\"GSTIN\", \"<br>GSTIN\") }}\n\t\t{% endif %}\n\t{% endif %}\n\t<br>\n\t{% if doc.docstatus == 0 %}\n\t\t<b>{{ doc.status + \" \"+ (doc.select_print_heading or _(\"Invoice\")) }}</b><br>\n\t{% else %}\n\t\t<b>{{ doc.select_print_heading or _(\"Invoice\") }}</b><br>\n\t{% endif %}\n</p>\n<p>\n\t<b>{{ _(\"Receipt No\") }}:</b> {{ doc.name }}<br>\n\t<b>{{ _(\"Date\") }}:</b> {{ doc.get_formatted(\"posting_date\") }}<br>\n\t{% if doc.grand_total > 50000 %}\n\t\t{% set customer_address = doc.address_display.replace(\"\\n\", \" \").replace(\"<br>\", \" \") %}\n\t\t<b>{{ _(\"Customer\") }}:</b><br>\n\t\t{{ doc.customer_name }}<br>\n\t\t{{ customer_address }}\n\t{% endif %}\n</p>\n\n<hr>\n<table class=\"table table-condensed cart no-border\">\n\t<thead>\n\t\t<tr>\n\t\t\t<th width=\"50%\">{{ _(\"Item\") }}</b></th>\n\t\t\t<th width=\"25%\" class=\"text-right\">{{ _(\"Qty\") }}</th>\n\t\t\t<th width=\"25%\" class=\"text-right\">{{ _(\"Amount\") }}</th>\n\t\t</tr>\n\t</thead>\n\t<tbody>\n\t\t{%- for item in doc.items -%}\n\t\t<tr>\n\t\t\t<td>\n\t\t\t\t{{ item.item_code }}\n\t\t\t\t{%- if item.item_name != item.item_code -%}\n\t\t\t\t\t<br>{{ item.item_name }}\n\t\t\t\t{%- endif -%}\n\t\t\t\t{%- if item.gst_hsn_code -%}\n\t\t\t\t\t<br><b>{{ _(\"HSN/SAC\") }}:</b> {{ item.gst_hsn_code }}\n\t\t\t\t{%- endif -%}\n\t\t\t\t{%- if item.serial_no -%}\n\t\t\t\t\t<br><b>{{ _(\"SR.No\") }}:</b><br>\n\t\t\t\t\t{{ item.serial_no | replace(\"\\n\", \", \") }}\n\t\t\t\t{%- endif -%}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">{{ item.qty }}<br>@ {{ item.rate }}</td>\n\t\t\t<td class=\"text-right\">{{ item.get_formatted(\"amount\") }}</td>\n\t\t</tr>\n\t\t{%- endfor -%}\n\t</tbody>\n</table>\n<table class=\"table table-condensed no-border\">\n\t<tbody>\n\t\t<tr>\n\t\t\t{% if doc.flags.show_inclusive_tax_in_print %}\n\t\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t\t{{ _(\"Total Excl. Tax\") }}\n\t\t\t\t</td>\n\t\t\t\t<td class=\"text-right\">\n\t\t\t\t\t{{ doc.get_formatted(\"net_total\", doc) }}\n\t\t\t\t</td>\n\t\t\t{% else %}\n\t\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t\t{{ _(\"Total\") }}\n\t\t\t\t</td>\n\t\t\t\t<td class=\"text-right\">\n\t\t\t\t\t{{ doc.get_formatted(\"total\", doc) }}\n\t\t\t\t</td>\n\t\t\t{% endif %}\n\t\t</tr>\n\t\t{%- for row in doc.taxes -%}\n\t\t  {%- if (not row.included_in_print_rate or doc.flags.show_inclusive_tax_in_print) and row.tax_amount != 0 -%}\n\t\t\t<tr>\n\t\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t\t{% if '%' in row.description %}\n\t\t\t\t\t    {{ row.description }}\n\t\t\t\t\t{% else %}\n\t\t\t\t\t    {{ row.description }}@{{ row.rate }}%\n\t\t\t\t\t{% endif %}\n\t\t\t\t</td>\n\t\t\t\t<td class=\"text-right\">\n\t\t\t\t\t{{ row.get_formatted(\"tax_amount\", doc) }}\n\t\t\t\t</td>\n\t\t\t<tr>\n\t\t  {%- endif -%}\n\t\t{%- endfor -%}\n\t\t{%- if doc.discount_amount -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t{{ _(\"Discount\") }}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"discount_amount\") }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- endif -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t<b>{{ _(\"Grand Total\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"grand_total\") }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- if doc.rounded_total -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t<b>{{ _(\"Rounded Total\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"rounded_total\") }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- endif -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t<b>{{ _(\"Paid Amount\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"paid_amount\") }}\n\t\t\t</td>\n\t\t</tr>\n\t{%- if doc.change_amount -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t<b>{{ _(\"Change Amount\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"change_amount\") }}\n\t\t\t</td>\n\t\t</tr>\n\t{%- endif -%}\n\t</tbody>\n</table>\n<p>{{ doc.terms or \"\" }}</p>\n<p class=\"text-center\">{{ _(\"Thank you, please visit again.\") }}</p>",
+ "idx": 0,
+ "line_breaks": 0,
+ "modified": "2020-04-29 16:47:02.743246",
+ "modified_by": "Administrator",
+ "module": "Selling",
+ "name": "GST POS Invoice",
+ "owner": "Administrator",
+ "print_format_builder": 0,
+ "print_format_type": "Jinja",
+ "raw_printing": 0,
+ "show_section_headings": 0,
+ "standard": "Yes"
+}
\ No newline at end of file
diff --git a/erpnext/selling/doctype/pos_closing_voucher/__init__.py b/erpnext/selling/print_format/pos_invoice/__init__.py
similarity index 100%
copy from erpnext/selling/doctype/pos_closing_voucher/__init__.py
copy to erpnext/selling/print_format/pos_invoice/__init__.py
diff --git a/erpnext/selling/print_format/pos_invoice/pos_invoice.json b/erpnext/selling/print_format/pos_invoice/pos_invoice.json
new file mode 100644
index 0000000..99094ed
--- /dev/null
+++ b/erpnext/selling/print_format/pos_invoice/pos_invoice.json
@@ -0,0 +1,22 @@
+{
+ "align_labels_right": 0,
+ "creation": "2011-12-21 11:08:55",
+ "custom_format": 1,
+ "disabled": 0,
+ "doc_type": "POS Invoice",
+ "docstatus": 0,
+ "doctype": "Print Format",
+ "html": "<style>\n\t.print-format table, .print-format tr, \n\t.print-format td, .print-format div, .print-format p {\n\t\tfont-family: Tahoma, sans-serif;\n\t\tline-height: 150%;\n\t\tvertical-align: middle;\n\t}\n\t@media screen {\n\t\t.print-format {\n\t\t\twidth: 4in;\n\t\t\tpadding: 0.25in;\n\t\t\tmin-height: 8in;\n\t\t}\n\t}\n</style>\n\n{% if letter_head %}\n    {{ letter_head }}\n{% endif %}\n\n<p class=\"text-center\" style=\"margin-bottom: 1rem\">\n\t{{ doc.company }}<br>\n\t{{ doc.select_print_heading or _(\"Invoice\") }}<br>\n</p>\n<p>\n\t<b>{{ _(\"Receipt No\") }}:</b> {{ doc.name }}<br>\n\t<b>{{ _(\"Date\") }}:</b> {{ doc.get_formatted(\"posting_date\") }}<br>\n\t<b>{{ _(\"Customer\") }}:</b> {{ doc.customer_name }}\n</p>\n\n<hr>\n<table class=\"table table-condensed cart no-border\">\n\t<thead>\n\t\t<tr>\n\t\t\t<th width=\"50%\">{{ _(\"Item\") }}</th>\n\t\t\t<th width=\"25%\" class=\"text-right\">{{ _(\"Qty\") }}</th>\n\t\t\t<th width=\"25%\" class=\"text-right\">{{ _(\"Amount\") }}</th>\n\t\t</tr>\n\t</thead>\n\t<tbody>\n\t\t{%- for item in doc.items -%}\n\t\t<tr>\n\t\t\t<td>\n\t\t\t\t{{ item.item_code }}\n\t\t\t\t{%- if item.item_name != item.item_code -%}\n\t\t\t\t\t<br>{{ item.item_name }}\n\t\t\t\t{%- endif -%}\n\t\t\t\t{%- if item.serial_no -%}\n\t\t\t\t\t<br><b>{{ _(\"SR.No\") }}:</b><br>\n\t\t\t\t\t{{ item.serial_no | replace(\"\\n\", \", \") }}\n\t\t\t\t{%- endif -%}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">{{ item.qty }}<br>@ {{ item.get_formatted(\"rate\") }}</td>\n\t\t\t<td class=\"text-right\">{{ item.get_formatted(\"amount\") }}</td>\n\t\t</tr>\n\t\t{%- endfor -%}\n\t</tbody>\n</table>\n<table class=\"table table-condensed no-border\">\n\t<tbody>\n\t\t<tr>\n\t\t\t{% if doc.flags.show_inclusive_tax_in_print %}\n\t\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t\t{{ _(\"Total Excl. Tax\") }}\n\t\t\t\t</td>\n\t\t\t\t<td class=\"text-right\">\n\t\t\t\t\t{{ doc.get_formatted(\"net_total\", doc) }}\n\t\t\t\t</td>\n\t\t\t{% else %}\n\t\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t\t{{ _(\"Total\") }}\n\t\t\t\t</td>\n\t\t\t\t<td class=\"text-right\">\n\t\t\t\t\t{{ doc.get_formatted(\"total\", doc) }}\n\t\t\t\t</td>\n\t\t\t{% endif %}\n\t\t</tr>\n\t\t{%- for row in doc.taxes -%}\n\t\t  {%- if not row.included_in_print_rate or doc.flags.show_inclusive_tax_in_print -%}\n\t\t\t<tr>\n\t\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t    {% if '%' in row.description %}\n\t\t\t\t\t    {{ row.description }}\n\t\t\t\t\t{% else %}\n\t\t\t\t\t    {{ row.description }}@{{ row.rate }}%\n\t\t\t\t\t{% endif %}\n\t\t\t\t</td>\n\t\t\t\t<td class=\"text-right\">\n\t\t\t\t\t{{ row.get_formatted(\"tax_amount\", doc) }}\n\t\t\t\t</td>\n\t\t\t<tr>\n\t\t  {%- endif -%}\n\t\t{%- endfor -%}\n\n\t\t{%- if doc.discount_amount -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t{{ _(\"Discount\") }}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"discount_amount\") }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- endif -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t<b>{{ _(\"Grand Total\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"grand_total\") }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- if doc.rounded_total -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t<b>{{ _(\"Rounded Total\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"rounded_total\") }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- endif -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t<b>{{ _(\"Paid Amount\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"paid_amount\") }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- if doc.change_amount -%}\n\t\t\t<tr>\n\t\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t\t<b>{{ _(\"Change Amount\") }}</b>\n\t\t\t\t</td>\n\t\t\t\t<td class=\"text-right\">\n\t\t\t\t\t{{ doc.get_formatted(\"change_amount\") }}\n\t\t\t\t</td>\n\t\t\t</tr>\n\t\t{%- endif -%}\n\t</tbody>\n</table>\n<hr>\n<p>{{ doc.terms or \"\" }}</p>\n<p class=\"text-center\">{{ _(\"Thank you, please visit again.\") }}</p>",
+ "idx": 1,
+ "line_breaks": 0,
+ "modified": "2020-04-29 16:45:58.942375",
+ "modified_by": "Administrator",
+ "module": "Selling",
+ "name": "POS Invoice",
+ "owner": "Administrator",
+ "print_format_builder": 0,
+ "print_format_type": "Jinja",
+ "raw_printing": 0,
+ "show_section_headings": 0,
+ "standard": "Yes"
+}
\ No newline at end of file
diff --git a/erpnext/selling/doctype/pos_closing_voucher/__init__.py b/erpnext/selling/print_format/return_pos_invoice/__init__.py
similarity index 100%
copy from erpnext/selling/doctype/pos_closing_voucher/__init__.py
copy to erpnext/selling/print_format/return_pos_invoice/__init__.py
diff --git a/erpnext/selling/print_format/return_pos_invoice/return_pos_invoice.json b/erpnext/selling/print_format/return_pos_invoice/return_pos_invoice.json
new file mode 100644
index 0000000..d7f3350
--- /dev/null
+++ b/erpnext/selling/print_format/return_pos_invoice/return_pos_invoice.json
@@ -0,0 +1,24 @@
+{
+ "align_labels_right": 0,
+ "creation": "2020-05-14 17:02:44.207166",
+ "custom_format": 1,
+ "default_print_language": "en",
+ "disabled": 0,
+ "doc_type": "POS Invoice",
+ "docstatus": 0,
+ "doctype": "Print Format",
+ "font": "Default",
+ "html": "<style>\n\t.print-format table, .print-format tr, \n\t.print-format td, .print-format div, .print-format p {\n\t\tfont-family: Tahoma, sans-serif;\n\t\tline-height: 150%;\n\t\tvertical-align: middle;\n\t}\n\t@media screen {\n\t\t.print-format {\n\t\t\twidth: 4in;\n\t\t\tpadding: 0.25in;\n\t\t\tmin-height: 8in;\n\t\t}\n\t}\n</style>\n\n{% if letter_head %}\n    {{ letter_head }}\n{% endif %}\n\n<p class=\"text-center\" style=\"margin-bottom: 1rem\">\n\t{{ doc.company }}<br>\n\t{{ doc.select_print_heading or _(\"Return Invoice\") }}<br>\n</p>\n<p>\n\t<b>{{ _(\"Receipt No\") }}:</b> {{ doc.name }}<br>\n\t<b>{{ _(\"Original Invoice\") }}:</b> {{ doc.return_against }}<br>\n\t<b>{{ _(\"Date\") }}:</b> {{ doc.get_formatted(\"posting_date\") }}<br>\n\t<b>{{ _(\"Customer\") }}:</b> {{ doc.customer_name }}\n</p>\n\n<hr>\n<table class=\"table table-condensed cart no-border\">\n\t<thead>\n\t\t<tr>\n\t\t\t<th width=\"50%\">{{ _(\"Item\") }}</th>\n\t\t\t<th width=\"25%\" class=\"text-right\">{{ _(\"Qty\") }}</th>\n\t\t\t<th width=\"25%\" class=\"text-right\">{{ _(\"Amount\") }}</th>\n\t\t</tr>\n\t</thead>\n\t<tbody>\n\t\t{%- for item in doc.items -%}\n\t\t<tr>\n\t\t\t<td>\n\t\t\t\t{{ item.item_code }}\n\t\t\t\t{%- if item.item_name != item.item_code -%}\n\t\t\t\t\t<br>{{ item.item_name }}\n\t\t\t\t{%- endif -%}\n\t\t\t\t{%- if item.serial_no -%}\n\t\t\t\t\t<br><b>{{ _(\"SR.No\") }}:</b><br>\n\t\t\t\t\t{{ item.serial_no | replace(\"\\n\", \", \") }}\n\t\t\t\t{%- endif -%}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">{{ item.qty }}<br>@ {{ item.get_formatted(\"rate\") }}</td>\n\t\t\t<td class=\"text-right\">{{ item.get_formatted(\"amount\") }}</td>\n\t\t</tr>\n\t\t{%- endfor -%}\n\t</tbody>\n</table>\n<table class=\"table table-condensed no-border\">\n\t<tbody>\n\t\t<tr>\n\t\t\t{% if doc.flags.show_inclusive_tax_in_print %}\n\t\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t\t{{ _(\"Total Excl. Tax\") }}\n\t\t\t\t</td>\n\t\t\t\t<td class=\"text-right\">\n\t\t\t\t\t{{ doc.get_formatted(\"net_total\", doc) }}\n\t\t\t\t</td>\n\t\t\t{% else %}\n\t\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t\t{{ _(\"Total\") }}\n\t\t\t\t</td>\n\t\t\t\t<td class=\"text-right\">\n\t\t\t\t\t{{ doc.get_formatted(\"total\", doc) }}\n\t\t\t\t</td>\n\t\t\t{% endif %}\n\t\t</tr>\n\t\t{%- for row in doc.taxes -%}\n\t\t  {%- if not row.included_in_print_rate or doc.flags.show_inclusive_tax_in_print -%}\n\t\t\t<tr>\n\t\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t    {% if '%' in row.description %}\n\t\t\t\t\t    {{ row.description }}\n\t\t\t\t\t{% else %}\n\t\t\t\t\t    {{ row.description }}@{{ row.rate }}%\n\t\t\t\t\t{% endif %}\n\t\t\t\t</td>\n\t\t\t\t<td class=\"text-right\">\n\t\t\t\t\t{{ row.get_formatted(\"tax_amount\", doc)}}\n\t\t\t\t</td>\n\t\t\t<tr>\n\t\t  {%- endif -%}\n\t\t{%- endfor -%}\n\n\t\t{%- if doc.discount_amount -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t{{ _(\"Discount\") }}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"discount_amount\") }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- endif -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t<b>{{ _(\"Grand Total\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"grand_total\") }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- if doc.rounded_total -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t<b>{{ _(\"Rounded Total\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"rounded_total\") }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- endif -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t<b>{{ _(\"Paid Amount\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"paid_amount\") }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- if doc.change_amount -%}\n\t\t\t<tr>\n\t\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t\t<b>{{ _(\"Change Amount\") }}</b>\n\t\t\t\t</td>\n\t\t\t\t<td class=\"text-right\">\n\t\t\t\t\t{{ doc.get_formatted(\"change_amount\")}}\n\t\t\t\t</td>\n\t\t\t</tr>\n\t\t{%- endif -%}\n\t</tbody>\n</table>\n<hr>\n<p>{{ doc.terms or \"\" }}</p>\n<p class=\"text-center\">{{ _(\"Thank you, please visit again.\") }}</p>",
+ "idx": 0,
+ "line_breaks": 0,
+ "modified": "2020-05-14 17:13:29.354015",
+ "modified_by": "Administrator",
+ "module": "Selling",
+ "name": "Return POS Invoice",
+ "owner": "Administrator",
+ "print_format_builder": 0,
+ "print_format_type": "Jinja",
+ "raw_printing": 0,
+ "show_section_headings": 0,
+ "standard": "Yes"
+}
\ No newline at end of file
diff --git a/erpnext/selling/report/item_wise_sales_history/item_wise_sales_history.py b/erpnext/selling/report/item_wise_sales_history/item_wise_sales_history.py
index bd59be6..0a70b97 100644
--- a/erpnext/selling/report/item_wise_sales_history/item_wise_sales_history.py
+++ b/erpnext/selling/report/item_wise_sales_history/item_wise_sales_history.py
@@ -9,6 +9,9 @@
 
 def execute(filters=None):
 	filters = frappe._dict(filters or {})
+	if filters.from_date > filters.to_date:
+		frappe.throw(_('From Date cannot be greater than To Date'))
+	
 	columns = get_columns(filters)
 	data = get_data(filters)
 
@@ -188,7 +191,7 @@
 		conditions += "AND so_item.item_code = '%s'" %frappe.db.escape(filters.item_code)
 
 	if filters.get("customer"):
-		conditions += "AND so.customer = '%s'" %frappe.db.escape(filters.customer)
+		conditions += "AND so.customer = %s" %frappe.db.escape(filters.customer)
 
 	return conditions
 
diff --git a/erpnext/selling/report/pending_so_items_for_purchase_request/pending_so_items_for_purchase_request.py b/erpnext/selling/report/pending_so_items_for_purchase_request/pending_so_items_for_purchase_request.py
index 14d8031..e89c451 100644
--- a/erpnext/selling/report/pending_so_items_for_purchase_request/pending_so_items_for_purchase_request.py
+++ b/erpnext/selling/report/pending_so_items_for_purchase_request/pending_so_items_for_purchase_request.py
@@ -158,7 +158,7 @@
 				}
 				pending_so.append(so_record)
 		else:
-			for item in bundled_item_map.get((so.name, so.item_code)):
+			for item in bundled_item_map.get((so.name, so.item_code), []):
 				material_requests_against_so = materials_request_dict.get((so.name, item.item_code)) or {}
 				if flt(item.qty) > flt(material_requests_against_so.get('qty')):
 					so_record = {
diff --git a/erpnext/selling/sales_common.js b/erpnext/selling/sales_common.js
index 4a7dd5a..333a563 100644
--- a/erpnext/selling/sales_common.js
+++ b/erpnext/selling/sales_common.js
@@ -142,7 +142,7 @@
 		frappe.model.round_floats_in(item, ["price_list_rate", "discount_percentage"]);
 
 		// check if child doctype is Sales Order Item/Qutation Item and calculate the rate
-		if(in_list(["Quotation Item", "Sales Order Item", "Delivery Note Item", "Sales Invoice Item"]), cdt)
+		if(in_list(["Quotation Item", "Sales Order Item", "Delivery Note Item", "Sales Invoice Item", "POS Invoice Item"]), cdt)
 			this.apply_pricing_rule_on_item(item);
 		else
 			item.rate = flt(item.price_list_rate * (1 - item.discount_percentage / 100.0),
@@ -312,6 +312,11 @@
 	batch_no: function(doc, cdt, cdn) {
 		var me = this;
 		var item = frappe.get_doc(cdt, cdn);
+
+		if (item.serial_no) {
+			return;
+		}
+
 		item.serial_no = null;
 		var has_serial_no;
 		frappe.db.get_value('Item', {'item_code': item.item_code}, 'has_serial_no', (r) => {
diff --git a/erpnext/selling/selling_dashboard/selling/selling.json b/erpnext/selling/selling_dashboard/selling/selling.json
new file mode 100644
index 0000000..52e6714
--- /dev/null
+++ b/erpnext/selling/selling_dashboard/selling/selling.json
@@ -0,0 +1,46 @@
+{
+ "cards": [
+  {
+   "card": "Annual Sales"
+  },
+  {
+   "card": "Sales Orders to Deliver"
+  },
+  {
+   "card": "Sales Orders to Bill"
+  },
+  {
+   "card": "Active Customers"
+  }
+ ],
+ "charts": [
+  {
+   "chart": "Sales Order Trends",
+   "width": "Full"
+  },
+  {
+   "chart": "Top Customers",
+   "width": "Half"
+  },
+  {
+   "chart": "Sales Order Analysis",
+   "width": "Half"
+  },
+  {
+   "chart": "Item-wise Annual Sales",
+   "width": "Full"
+  }
+ ],
+ "creation": "2020-07-20 20:17:16.688162",
+ "dashboard_name": "Selling",
+ "docstatus": 0,
+ "doctype": "Dashboard",
+ "idx": 0,
+ "is_default": 0,
+ "is_standard": 1,
+ "modified": "2020-07-22 15:31:22.299903",
+ "modified_by": "Administrator",
+ "module": "Selling",
+ "name": "Selling",
+ "owner": "Administrator"
+}
\ No newline at end of file
diff --git a/erpnext/setup/doctype/company/company.js b/erpnext/setup/doctype/company/company.js
index 875904f..7ae5385 100644
--- a/erpnext/setup/doctype/company/company.js
+++ b/erpnext/setup/doctype/company/company.js
@@ -264,7 +264,10 @@
 			["expenses_included_in_valuation",
 				{"root_type": "Expense", "account_type": "Expenses Included in Valuation"}],
 			["stock_received_but_not_billed",
-				{"root_type": "Liability", "account_type": "Stock Received But Not Billed"}]
+				{"root_type": "Liability", "account_type": "Stock Received But Not Billed"}],
+			["service_received_but_not_billed",
+				{"root_type": "Liability", "account_type": "Service Received But Not Billed"}],
+
 		], function(i, v) {
 			erpnext.company.set_custom_query(frm, v);
 		});
diff --git a/erpnext/setup/doctype/company/company.json b/erpnext/setup/doctype/company/company.json
index 020a93f..221044d 100644
--- a/erpnext/setup/doctype/company/company.json
+++ b/erpnext/setup/doctype/company/company.json
@@ -22,7 +22,6 @@
   "default_letter_head",
   "default_holiday_list",
   "default_finance_book",
-  "standard_working_hours",
   "default_selling_terms",
   "default_buying_terms",
   "default_warehouse_for_sales_return",
@@ -67,10 +66,12 @@
   "payment_terms",
   "auto_accounting_for_stock_settings",
   "enable_perpetual_inventory",
+  "enable_perpetual_inventory_for_non_stock_items",
   "default_inventory_account",
   "stock_adjustment_account",
   "column_break_32",
   "stock_received_but_not_billed",
+  "service_received_but_not_billed",
   "expenses_included_in_valuation",
   "fixed_asset_depreciation_settings",
   "accumulated_depreciation_account",
@@ -239,11 +240,6 @@
    "options": "Holiday List"
   },
   {
-   "fieldname": "standard_working_hours",
-   "fieldtype": "Float",
-   "label": "Standard Working Hours"
-  },
-  {
    "fieldname": "default_warehouse_for_sales_return",
    "fieldtype": "Link",
    "label": "Default warehouse for Sales Return",
@@ -723,6 +719,20 @@
    "fieldtype": "Link",
    "label": "Default Buying Terms",
    "options": "Terms and Conditions"
+  },
+  {
+   "fieldname": "service_received_but_not_billed",
+   "fieldtype": "Link",
+   "ignore_user_permissions": 1,
+   "label": "Service Received But Not Billed",
+   "no_copy": 1,
+   "options": "Account"
+  },
+  {
+   "default": "0",
+   "fieldname": "enable_perpetual_inventory_for_non_stock_items",
+   "fieldtype": "Check",
+   "label": "Enable Perpetual Inventory For Non Stock Items"
   }
  ],
  "icon": "fa fa-building",
@@ -730,7 +740,7 @@
  "image_field": "company_logo",
  "is_tree": 1,
  "links": [],
- "modified": "2020-03-21 18:09:53.534211",
+ "modified": "2020-06-24 12:45:31.462195",
  "modified_by": "Administrator",
  "module": "Setup",
  "name": "Company",
diff --git a/erpnext/setup/doctype/company/company.py b/erpnext/setup/doctype/company/company.py
index 8bcaa28..47b41a9 100644
--- a/erpnext/setup/doctype/company/company.py
+++ b/erpnext/setup/doctype/company/company.py
@@ -46,6 +46,7 @@
 		self.validate_currency()
 		self.validate_coa_input()
 		self.validate_perpetual_inventory()
+		self.validate_perpetual_inventory_for_non_stock_items()
 		self.check_country_change()
 		self.set_chart_of_accounts()
 		self.validate_parent_company()
@@ -182,6 +183,12 @@
 				frappe.msgprint(_("Set default inventory account for perpetual inventory"),
 					alert=True, indicator='orange')
 
+	def validate_perpetual_inventory_for_non_stock_items(self):
+		if not self.get("__islocal"):
+			if cint(self.enable_perpetual_inventory_for_non_stock_items) == 1 and not self.service_received_but_not_billed:
+				frappe.throw(_("Set default {0} account for perpetual inventory for non stock items").format(
+					frappe.bold('Service Received But Not Billed')))
+
 	def check_country_change(self):
 		frappe.flags.country_change = False
 
diff --git a/erpnext/setup/doctype/customer_group/customer_group.js b/erpnext/setup/doctype/customer_group/customer_group.js
index c199a8e..44a5019 100644
--- a/erpnext/setup/doctype/customer_group/customer_group.js
+++ b/erpnext/setup/doctype/customer_group/customer_group.js
@@ -8,7 +8,7 @@
 
 cur_frm.cscript.set_root_readonly = function(doc) {
 	// read-only for root customer group
-	if(!doc.parent_customer_group) {
+	if(!doc.parent_customer_group && !doc.__islocal) {
 		cur_frm.set_read_only();
 		cur_frm.set_intro(__("This is a root customer group and cannot be edited."));
 	} else {
@@ -20,7 +20,8 @@
 cur_frm.fields_dict['parent_customer_group'].get_query = function(doc,cdt,cdn) {
 	return {
 		filters: {
-			'is_group': 1
+			'is_group': 1,
+			'name': ['!=', cur_frm.doc.customer_group_name]
 		}
 	}
 }
diff --git a/erpnext/setup/doctype/customer_group/customer_group.py b/erpnext/setup/doctype/customer_group/customer_group.py
index f62613e..68e1ccb 100644
--- a/erpnext/setup/doctype/customer_group/customer_group.py
+++ b/erpnext/setup/doctype/customer_group/customer_group.py
@@ -6,9 +6,12 @@
 from frappe import _
 
 
-from frappe.utils.nestedset import NestedSet
+from frappe.utils.nestedset import NestedSet, get_root_of
 class CustomerGroup(NestedSet):
 	nsm_parent_field = 'parent_customer_group'
+	def validate(self):
+		if not self.parent_customer_group:
+			self.parent_customer_group = get_root_of("Customer Group")
 
 	def on_update(self):
 		self.validate_name_with_customer()
diff --git a/erpnext/setup/doctype/email_digest/email_digest.py b/erpnext/setup/doctype/email_digest/email_digest.py
index 7c0be3b..b30bd78 100644
--- a/erpnext/setup/doctype/email_digest/email_digest.py
+++ b/erpnext/setup/doctype/email_digest/email_digest.py
@@ -405,8 +405,8 @@
 
 		value, count = frappe.db.sql("""select ifnull((sum(grand_total)) - (sum(grand_total*per_billed/100)),0),
                     count(*) from `tabSales Order`
-					where (transaction_date <= %(to_date)s) and billing_status != "Fully Billed"
-					and status not in ('Closed','Cancelled', 'Completed') """, {"to_date": self.future_to_date})[0]
+					where (transaction_date <= %(to_date)s) and billing_status != "Fully Billed" and company = %(company)s
+					and status not in ('Closed','Cancelled', 'Completed') """, {"to_date": self.future_to_date, "company": self.company})[0]
 
 		label = get_link_to_report('Sales Order', label=self.meta.get_label("sales_orders_to_bill"),
 			report_type="Report Builder",
@@ -430,8 +430,8 @@
 
 		value, count = frappe.db.sql("""select ifnull((sum(grand_total)) - (sum(grand_total*per_delivered/100)),0),
 					count(*) from `tabSales Order`
-					where (transaction_date <= %(to_date)s) and delivery_status != "Fully Delivered"
-					and status not in ('Closed','Cancelled', 'Completed') """, {"to_date": self.future_to_date})[0]
+					where (transaction_date <= %(to_date)s) and delivery_status != "Fully Delivered" and company = %(company)s
+					and status not in ('Closed','Cancelled', 'Completed') """, {"to_date": self.future_to_date, "company": self.company})[0]
 
 		label = get_link_to_report('Sales Order', label=self.meta.get_label("sales_orders_to_deliver"),
 			report_type="Report Builder",
@@ -455,8 +455,8 @@
 
 		value, count = frappe.db.sql("""select ifnull((sum(grand_total))-(sum(grand_total*per_received/100)),0),
                     count(*) from `tabPurchase Order`
-					where (transaction_date <= %(to_date)s) and per_received < 100
-					and status not in ('Closed','Cancelled', 'Completed') """, {"to_date": self.future_to_date})[0]
+					where (transaction_date <= %(to_date)s) and per_received < 100 and company = %(company)s
+					and status not in ('Closed','Cancelled', 'Completed') """, {"to_date": self.future_to_date, "company": self.company})[0]
 
 		label = get_link_to_report('Purchase Order', label=self.meta.get_label("purchase_orders_to_receive"),
 			report_type="Report Builder",
@@ -480,8 +480,8 @@
 
 		value, count = frappe.db.sql("""select ifnull((sum(grand_total)) - (sum(grand_total*per_billed/100)),0),
                     count(*) from `tabPurchase Order`
-					where (transaction_date <= %(to_date)s) and per_billed < 100
-					and status not in ('Closed','Cancelled', 'Completed') """, {"to_date": self.future_to_date})[0]
+					where (transaction_date <= %(to_date)s) and per_billed < 100 and company = %(company)s
+					and status not in ('Closed','Cancelled', 'Completed') """, {"to_date": self.future_to_date, "company": self.company})[0]
 
 		label = get_link_to_report('Purchase Order', label=self.meta.get_label("purchase_orders_to_bill"),
 			report_type="Report Builder",
diff --git a/erpnext/setup/doctype/item_group/item_group.js b/erpnext/setup/doctype/item_group/item_group.js
index df22231..9892dc3 100644
--- a/erpnext/setup/doctype/item_group/item_group.js
+++ b/erpnext/setup/doctype/item_group/item_group.js
@@ -66,7 +66,7 @@
 	set_root_readonly: function(frm) {
 		// read-only for root item group
 		frm.set_intro("");
-		if(!frm.doc.parent_item_group) {
+		if(!frm.doc.parent_item_group && !frm.doc.__islocal) {
 			frm.set_read_only();
 			frm.set_intro(__("This is a root item group and cannot be edited."), true);
 		}
diff --git a/erpnext/setup/doctype/sales_person/sales_person.js b/erpnext/setup/doctype/sales_person/sales_person.js
index 89ca4a9..8f7593d 100644
--- a/erpnext/setup/doctype/sales_person/sales_person.js
+++ b/erpnext/setup/doctype/sales_person/sales_person.js
@@ -19,7 +19,7 @@
 				}
 			}
 		};
-	
+
 		frm.make_methods = {
 			'Sales Order': () => frappe.new_doc("Sales Order")
 				.then(() => frm.add_child("sales_team", {"sales_person": frm.doc.name}))
@@ -33,7 +33,7 @@
 
 cur_frm.cscript.set_root_readonly = function(doc) {
 	// read-only for root
-	if(!doc.parent_sales_person) {
+	if(!doc.parent_sales_person && !doc.__islocal) {
 		cur_frm.set_read_only();
 		cur_frm.set_intro(__("This is a root sales person and cannot be edited."));
 	} else {
diff --git a/erpnext/setup/doctype/sales_person/sales_person.py b/erpnext/setup/doctype/sales_person/sales_person.py
index 3379534..19c2e5b 100644
--- a/erpnext/setup/doctype/sales_person/sales_person.py
+++ b/erpnext/setup/doctype/sales_person/sales_person.py
@@ -5,13 +5,16 @@
 import frappe
 from frappe import _
 from frappe.utils import flt
-from frappe.utils.nestedset import NestedSet
+from frappe.utils.nestedset import NestedSet, get_root_of
 from erpnext import get_default_currency
 
 class SalesPerson(NestedSet):
 	nsm_parent_field = 'parent_sales_person'
 
 	def validate(self):
+		if not self.parent_sales_person:
+			self.parent_sales_person = get_root_of("Sales Person")
+
 		for d in self.get('targets') or []:
 			if not flt(d.target_qty) and not flt(d.target_amount):
 				frappe.throw(_("Either target qty or target amount is mandatory."))
diff --git a/erpnext/setup/doctype/supplier_group/supplier_group.js b/erpnext/setup/doctype/supplier_group/supplier_group.js
index ac5bda6..e75030d 100644
--- a/erpnext/setup/doctype/supplier_group/supplier_group.js
+++ b/erpnext/setup/doctype/supplier_group/supplier_group.js
@@ -8,7 +8,7 @@
 
 cur_frm.cscript.set_root_readonly = function(doc) {
 	// read-only for root customer group
-	if(!doc.parent_supplier_group) {
+	if(!doc.parent_supplier_group && !doc.__islocal) {
 		cur_frm.set_read_only();
 		cur_frm.set_intro(__("This is a root supplier group and cannot be edited."));
 	} else {
@@ -20,7 +20,8 @@
 cur_frm.fields_dict['parent_supplier_group'].get_query = function() {
 	return {
 		filters: {
-			'is_group': 1
+			'is_group': 1,
+			'name': ['!=', cur_frm.doc.supplier_group_name]
 		}
 	};
 };
diff --git a/erpnext/setup/doctype/territory/territory.js b/erpnext/setup/doctype/territory/territory.js
index 1eb9958..ceec47ae 100644
--- a/erpnext/setup/doctype/territory/territory.js
+++ b/erpnext/setup/doctype/territory/territory.js
@@ -20,7 +20,7 @@
 
 cur_frm.cscript.set_root_readonly = function(doc) {
 	// read-only for root territory
-	if(!doc.parent_territory) {
+	if(!doc.parent_territory && !doc.__islocal) {
 		cur_frm.set_read_only();
 		cur_frm.set_intro(__("This is a root territory and cannot be edited."));
 	} else {
diff --git a/erpnext/setup/doctype/territory/territory.py b/erpnext/setup/doctype/territory/territory.py
index 808b538..05e8f66 100644
--- a/erpnext/setup/doctype/territory/territory.py
+++ b/erpnext/setup/doctype/territory/territory.py
@@ -6,12 +6,14 @@
 from frappe.utils import flt
 from frappe import _
 
-from frappe.utils.nestedset import NestedSet
+from frappe.utils.nestedset import NestedSet, get_root_of
 
 class Territory(NestedSet):
 	nsm_parent_field = 'parent_territory'
 
 	def validate(self):
+		if not self.parent_territory:
+			self.parent_territory = get_root_of("Territory")
 
 		for d in self.get('targets') or []:
 			if not flt(d.target_qty) and not flt(d.target_amount):
diff --git a/erpnext/setup/install.py b/erpnext/setup/install.py
index 74ff0ec..aa9fbc0 100644
--- a/erpnext/setup/install.py
+++ b/erpnext/setup/install.py
@@ -29,12 +29,10 @@
 
 
 def check_setup_wizard_not_completed():
-	if frappe.db.get_default('desktop:home_page') == 'desktop':
-		print()
-		print("ERPNext can only be installed on a fresh site where the setup wizard is not completed")
-		print("You can reinstall this site (after saving your data) using: bench --site [sitename] reinstall")
-		print()
-		return False
+	if frappe.db.get_default('desktop:home_page') != 'setup-wizard':
+		message = """ERPNext can only be installed on a fresh site where the setup wizard is not completed. 
+You can reinstall this site (after saving your data) using: bench --site [sitename] reinstall"""
+		frappe.throw(message)
 
 
 def set_single_defaults():
@@ -105,4 +103,3 @@
 		"ref_doctype": "Company"
 	})
 	settings.save()
-
diff --git a/erpnext/shopping_cart/doctype/shopping_cart_settings/shopping_cart_settings.js b/erpnext/shopping_cart/doctype/shopping_cart_settings/shopping_cart_settings.js
index e1510f5..14500ba 100644
--- a/erpnext/shopping_cart/doctype/shopping_cart_settings/shopping_cart_settings.js
+++ b/erpnext/shopping_cart/doctype/shopping_cart_settings/shopping_cart_settings.js
@@ -1,25 +1,16 @@
 // Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
 // License: GNU General Public License v3. See license.txt
 
-$.extend(cur_frm.cscript, {
-	onload: function() {
-		if(cur_frm.doc.__onload && cur_frm.doc.__onload.quotation_series) {
-			cur_frm.fields_dict.quotation_series.df.options = cur_frm.doc.__onload.quotation_series;
-			cur_frm.refresh_field("quotation_series");
+frappe.ui.form.on("Shopping Cart Settings", {
+	onload: function(frm) {
+		if(frm.doc.__onload && frm.doc.__onload.quotation_series) {
+			frm.fields_dict.quotation_series.df.options = frm.doc.__onload.quotation_series;
+			frm.refresh_field("quotation_series");
 		}
 	},
-	refresh: function(){
-		toggle_mandatory(cur_frm)
-	},
-	enable_checkout: function(){
-		toggle_mandatory(cur_frm)
+	enabled: function(frm) {
+		if (frm.doc.enabled === 1) {
+			frm.set_value('enable_variants', 1);
+		}
 	}
 });
-
-
-function toggle_mandatory (cur_frm){
-	cur_frm.toggle_reqd("payment_gateway_account", false);
-	if(cur_frm.doc.enabled && cur_frm.doc.enable_checkout) {
-		cur_frm.toggle_reqd("payment_gateway_account", true);
-	}
-}
diff --git a/erpnext/shopping_cart/doctype/shopping_cart_settings/shopping_cart_settings.json b/erpnext/shopping_cart/doctype/shopping_cart_settings/shopping_cart_settings.json
index e828f54..c574afa 100644
--- a/erpnext/shopping_cart/doctype/shopping_cart_settings/shopping_cart_settings.json
+++ b/erpnext/shopping_cart/doctype/shopping_cart_settings/shopping_cart_settings.json
@@ -1,750 +1,192 @@
 {
-   "allow_copy": 0,
-   "allow_events_in_timeline": 0,
-   "allow_guest_to_view": 0,
-   "allow_import": 0,
-   "allow_rename": 0,
-   "beta": 0,
-   "creation": "2013-06-19 15:57:32",
-   "custom": 0,
-   "description": "Default settings for Shopping Cart",
-   "docstatus": 0,
-   "doctype": "DocType",
-   "document_type": "System",
-   "editable_grid": 0,
-   "fields": [
-    {
-     "allow_bulk_edit": 0,
-     "allow_in_quick_entry": 0,
-     "allow_on_submit": 0,
-     "bold": 0,
-     "collapsible": 0,
-     "columns": 0,
-     "fieldname": "enabled",
-     "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": "Enable Shopping Cart",
-     "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,
-     "depends_on": "",
-     "description": "",
-     "fieldname": "display_settings",
-     "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": "Display Settings",
-     "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,
-     "depends_on": "",
-     "description": "",
-     "fieldname": "show_attachments",
-     "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": "Show Public Attachments",
-     "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,
-     "depends_on": "",
-     "description": "",
-     "fieldname": "show_price",
-     "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": "Show Price",
-     "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,
-     "fieldname": "show_stock_availability",
-     "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": "Show Stock Availability",
-     "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,
-     "fieldname": "show_configure_button",
-     "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": "Show Configure Button",
-     "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,
-     "fieldname": "show_contact_us_button",
-     "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": "Show Contact Us Button",
-     "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,
-     "depends_on": "show_stock_availability",
-     "fieldname": "show_quantity_in_website",
-     "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": "Show Stock Quantity",
-     "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, 
-     "depends_on": "", 
-     "fetch_if_empty": 0, 
-     "fieldname": "show_apply_coupon_code_in_website", 
-     "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": "Show Apply Coupon Code", 
-     "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": "allow_items_not_in_stock",
-     "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": "Allow items not in stock to be added to cart",
-     "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,
-     "depends_on": "enabled",
-     "fieldname": "section_break_2",
-     "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,
-     "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,
-     "depends_on": "",
-     "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,
-     "print_hide": 0,
-     "print_hide_if_no_value": 0,
-     "read_only": 0,
-     "remember_last_selected_value": 1,
-     "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,
-     "description": "Prices will not be shown if Price List is not set",
-     "fieldname": "price_list",
-     "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": "Price List",
-     "length": 0,
-     "no_copy": 0,
-     "options": "Price List",
-     "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,
-     "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,
-     "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": "",
-     "fieldname": "default_customer_group",
-     "fieldtype": "Link",
-     "hidden": 0,
-     "ignore_user_permissions": 1,
-     "ignore_xss_filter": 0,
-     "in_filter": 0,
-     "in_global_search": 0,
-     "in_list_view": 0,
-     "in_standard_filter": 0,
-     "label": "Default Customer Group",
-     "length": 0,
-     "no_copy": 0,
-     "options": "Customer Group",
-     "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,
-     "fieldname": "quotation_series",
-     "fieldtype": "Select",
-     "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": "Quotation Series",
-     "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": 1,
-     "collapsible_depends_on": "eval:doc.enable_checkout",
-     "columns": 0,
-     "depends_on": "enabled",
-     "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,
-     "label": "Checkout Settings",
-     "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,
-     "collapsible_depends_on": "",
-     "columns": 0,
-     "depends_on": "",
-     "fieldname": "enable_checkout",
-     "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": "Enable Checkout",
-     "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,
-     "default": "Orders",
-     "description": "After payment completion redirect user to selected page.",
-     "fieldname": "payment_success_url",
-     "fieldtype": "Select",
-     "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 Success Url",
-     "length": 0,
-     "no_copy": 0,
-     "options": "\nOrders\nInvoices\nMy Account",
-     "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,
-     "fieldname": "column_break_11",
-     "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
-    },
-    {
-     "allow_bulk_edit": 0,
-     "allow_in_quick_entry": 0,
-     "allow_on_submit": 0,
-     "bold": 0,
-     "collapsible": 0,
-     "columns": 0,
-     "fieldname": "payment_gateway_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": "Payment Gateway Account",
-     "length": 0,
-     "no_copy": 0,
-     "options": "Payment Gateway Account",
-     "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
-    }
-   ],
-   "has_web_view": 0,
-   "hide_heading": 0,
-   "hide_toolbar": 0,
-   "icon": "fa fa-shopping-cart",
-   "idx": 1,
-   "image_view": 0,
-   "in_create": 0,
-   "is_submittable": 0,
-   "issingle": 1,
-   "istable": 0,
-   "max_attachments": 0,
-   "modified": "2019-10-14 13:54:24.575322",
-   "modified_by": "Administrator",
-   "module": "Shopping Cart",
-   "name": "Shopping Cart Settings",
-   "owner": "Administrator",
-   "permissions": [
-    {
-     "amend": 0,
-     "cancel": 0,
-     "create": 1,
-     "delete": 0,
-     "email": 1,
-     "export": 0,
-     "if_owner": 0,
-     "import": 0,
-     "permlevel": 0,
-     "print": 1,
-     "read": 1,
-     "report": 0,
-     "role": "Website Manager",
-     "set_user_permissions": 0,
-     "share": 1,
-     "submit": 0,
-     "write": 1
-    }
-   ],
-   "quick_entry": 0,
-   "read_only": 0,
-   "read_only_onload": 0,
-   "show_name_in_global_search": 0,
-   "sort_order": "ASC",
-   "track_changes": 0,
-   "track_seen": 0,
-   "track_views": 0
-  }
\ No newline at end of file
+ "actions": [],
+ "creation": "2013-06-19 15:57:32",
+ "description": "Default settings for Shopping Cart",
+ "doctype": "DocType",
+ "document_type": "System",
+ "engine": "InnoDB",
+ "field_order": [
+  "enabled",
+  "display_settings",
+  "show_attachments",
+  "show_price",
+  "show_stock_availability",
+  "enable_variants",
+  "column_break_7",
+  "show_contact_us_button",
+  "show_quantity_in_website",
+  "show_apply_coupon_code_in_website",
+  "allow_items_not_in_stock",
+  "section_break_2",
+  "company",
+  "price_list",
+  "column_break_4",
+  "default_customer_group",
+  "quotation_series",
+  "section_break_8",
+  "enable_checkout",
+  "payment_success_url",
+  "column_break_11",
+  "payment_gateway_account"
+ ],
+ "fields": [
+  {
+   "default": "0",
+   "fieldname": "enabled",
+   "fieldtype": "Check",
+   "in_list_view": 1,
+   "label": "Enable Shopping Cart"
+  },
+  {
+   "fieldname": "display_settings",
+   "fieldtype": "Section Break",
+   "label": "Display Settings"
+  },
+  {
+   "default": "0",
+   "fieldname": "show_attachments",
+   "fieldtype": "Check",
+   "label": "Show Public Attachments"
+  },
+  {
+   "default": "0",
+   "fieldname": "show_price",
+   "fieldtype": "Check",
+   "label": "Show Price"
+  },
+  {
+   "default": "0",
+   "fieldname": "show_stock_availability",
+   "fieldtype": "Check",
+   "label": "Show Stock Availability"
+  },
+  {
+   "default": "0",
+   "fieldname": "show_contact_us_button",
+   "fieldtype": "Check",
+   "label": "Show Contact Us Button"
+  },
+  {
+   "default": "0",
+   "depends_on": "show_stock_availability",
+   "fieldname": "show_quantity_in_website",
+   "fieldtype": "Check",
+   "label": "Show Stock Quantity"
+  },
+  {
+   "default": "0",
+   "fieldname": "show_apply_coupon_code_in_website",
+   "fieldtype": "Check",
+   "label": "Show Apply Coupon Code"
+  },
+  {
+   "default": "0",
+   "fieldname": "allow_items_not_in_stock",
+   "fieldtype": "Check",
+   "label": "Allow items not in stock to be added to cart"
+  },
+  {
+   "depends_on": "enabled",
+   "fieldname": "section_break_2",
+   "fieldtype": "Section Break"
+  },
+  {
+   "fieldname": "company",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "label": "Company",
+   "options": "Company",
+   "remember_last_selected_value": 1,
+   "reqd": 1
+  },
+  {
+   "description": "Prices will not be shown if Price List is not set",
+   "fieldname": "price_list",
+   "fieldtype": "Link",
+   "label": "Price List",
+   "options": "Price List"
+  },
+  {
+   "fieldname": "column_break_4",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "default_customer_group",
+   "fieldtype": "Link",
+   "ignore_user_permissions": 1,
+   "label": "Default Customer Group",
+   "options": "Customer Group",
+   "reqd": 1
+  },
+  {
+   "fieldname": "quotation_series",
+   "fieldtype": "Select",
+   "label": "Quotation Series",
+   "reqd": 1
+  },
+  {
+   "collapsible": 1,
+   "collapsible_depends_on": "eval:doc.enable_checkout",
+   "depends_on": "enabled",
+   "fieldname": "section_break_8",
+   "fieldtype": "Section Break",
+   "label": "Checkout Settings"
+  },
+  {
+   "default": "0",
+   "fieldname": "enable_checkout",
+   "fieldtype": "Check",
+   "label": "Enable Checkout"
+  },
+  {
+   "default": "Orders",
+   "description": "After payment completion redirect user to selected page.",
+   "fieldname": "payment_success_url",
+   "fieldtype": "Select",
+   "label": "Payment Success Url",
+   "options": "\nOrders\nInvoices\nMy Account"
+  },
+  {
+   "fieldname": "column_break_11",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "payment_gateway_account",
+   "fieldtype": "Link",
+   "label": "Payment Gateway Account",
+   "options": "Payment Gateway Account"
+  },
+  {
+   "fieldname": "column_break_7",
+   "fieldtype": "Column Break"
+  },
+  {
+   "default": "0",
+   "fieldname": "enable_variants",
+   "fieldtype": "Check",
+   "label": "Enable Variants"
+  }
+ ],
+ "icon": "fa fa-shopping-cart",
+ "idx": 1,
+ "issingle": 1,
+ "links": [],
+ "modified": "2020-07-17 17:53:22.667228",
+ "modified_by": "Administrator",
+ "module": "Shopping Cart",
+ "name": "Shopping Cart Settings",
+ "owner": "Administrator",
+ "permissions": [
+  {
+   "create": 1,
+   "email": 1,
+   "print": 1,
+   "read": 1,
+   "role": "Website Manager",
+   "share": 1,
+   "write": 1
+  }
+ ],
+ "sort_field": "modified",
+ "sort_order": "ASC"
+}
\ No newline at end of file
diff --git a/erpnext/shopping_cart/doctype/shopping_cart_settings/shopping_cart_settings.py b/erpnext/shopping_cart/doctype/shopping_cart_settings/shopping_cart_settings.py
index 3098190..c069b90 100644
--- a/erpnext/shopping_cart/doctype/shopping_cart_settings/shopping_cart_settings.py
+++ b/erpnext/shopping_cart/doctype/shopping_cart_settings/shopping_cart_settings.py
@@ -80,6 +80,7 @@
 
 	return frappe.local.shopping_cart_settings
 
+@frappe.whitelist(allow_guest=True)
 def is_cart_enabled():
 	return get_shopping_cart_settings().enabled
 
diff --git a/erpnext/shopping_cart/product_info.py b/erpnext/shopping_cart/product_info.py
index 7c08f5b..29617a8 100644
--- a/erpnext/shopping_cart/product_info.py
+++ b/erpnext/shopping_cart/product_info.py
@@ -55,7 +55,7 @@
 
 def set_product_info_for_website(item):
 	"""set product price uom for website"""
-	product_info = get_product_info_for_website(item.item_code, skip_quotation_creation=True)
+	product_info = get_product_info_for_website(item.item_code, skip_quotation_creation=True).get("product_info")
 
 	if product_info:
 		item.update(product_info)
diff --git a/erpnext/startup/leaderboard.py b/erpnext/startup/leaderboard.py
index 90ecd46..5545f13 100644
--- a/erpnext/startup/leaderboard.py
+++ b/erpnext/startup/leaderboard.py
@@ -50,11 +50,12 @@
 	return leaderboards
 
 @frappe.whitelist()
-def get_all_customers(from_date, company, field, limit = None):
+def get_all_customers(date_range, company, field, limit = None):
 	if field == "outstanding_amount":
 		filters = [['docstatus', '=', '1'], ['company', '=', company]]
-		if from_date:
-			filters.append(['posting_date', '>=', from_date])
+		if date_range:
+			date_range = frappe.parse_json(date_range)
+			filters.append(['posting_date', '>=', 'between', [date_range[0], date_range[1]]])
 		return frappe.db.get_all('Sales Invoice',
 			fields = ['customer as name', 'sum(outstanding_amount) as value'],
 			filters = filters,
@@ -68,18 +69,20 @@
 		elif field == "total_qty_sold":
 			select_field = "sum(so_item.stock_qty)"
 
+		date_condition = get_date_condition(date_range, 'so.transaction_date')
+
 		return frappe.db.sql("""
 			select so.customer as name, {0} as value
 			FROM `tabSales Order` as so JOIN `tabSales Order Item` as so_item
 				ON so.name = so_item.parent
-			where so.docstatus = 1 and so.transaction_date >= %s and so.company = %s
+			where so.docstatus = 1 {1} and so.company = %s
 			group by so.customer
 			order by value DESC
 			limit %s
-		""".format(select_field), (from_date, company, cint(limit)), as_dict=1) #nosec
+		""".format(select_field, date_condition), (company, cint(limit)), as_dict=1)
 
 @frappe.whitelist()
-def get_all_items(from_date, company, field, limit = None):
+def get_all_items(date_range, company, field, limit = None):
 	if field in ("available_stock_qty", "available_stock_value"):
 		select_field = "sum(actual_qty)" if field=="available_stock_qty" else "sum(stock_value)"
 		return frappe.db.get_all('Bin',
@@ -102,23 +105,25 @@
 			select_field = "sum(order_item.stock_qty)"
 			select_doctype = "Purchase Order"
 
+		date_condition = get_date_condition(date_range, 'sales_order.transaction_date')
+
 		return frappe.db.sql("""
 			select order_item.item_code as name, {0} as value
 			from `tab{1}` sales_order join `tab{1} Item` as order_item
 				on sales_order.name = order_item.parent
 			where sales_order.docstatus = 1
-				and sales_order.company = %s and sales_order.transaction_date >= %s
+				and sales_order.company = %s {2}
 			group by order_item.item_code
 			order by value desc
 			limit %s
-		""".format(select_field, select_doctype), (company, from_date, cint(limit)), as_dict=1) #nosec
+		""".format(select_field, select_doctype, date_condition), (company, cint(limit)), as_dict=1) #nosec
 
 @frappe.whitelist()
-def get_all_suppliers(from_date, company, field, limit = None):
+def get_all_suppliers(date_range, company, field, limit = None):
 	if field == "outstanding_amount":
 		filters = [['docstatus', '=', '1'], ['company', '=', company]]
-		if from_date:
-			filters.append(['posting_date', '>=', from_date])
+		if date_range:
+			filters.append(['posting_date', 'between' [date_range[0], date_range[1]]])
 		return frappe.db.get_all('Purchase Invoice',
 			fields = ['supplier as name', 'sum(outstanding_amount) as value'],
 			filters = filters,
@@ -132,18 +137,22 @@
 		elif field == "total_qty_purchased":
 			select_field = "sum(purchase_order_item.stock_qty)"
 
+		date_condition = get_date_condition(date_range, 'purchase_order.modified')
+
 		return frappe.db.sql("""
 			select purchase_order.supplier as name, {0} as value
 			FROM `tabPurchase Order` as purchase_order LEFT JOIN `tabPurchase Order Item`
 				as purchase_order_item ON purchase_order.name = purchase_order_item.parent
-			where purchase_order.docstatus = 1 and  purchase_order.modified >= %s
+			where
+				purchase_order.docstatus = 1
+				{1}
 				and  purchase_order.company = %s
 			group by purchase_order.supplier
 			order by value DESC
-			limit %s""".format(select_field), (from_date, company, cint(limit)), as_dict=1) #nosec
+			limit %s""".format(select_field, date_condition), (company, cint(limit)), as_dict=1) #nosec
 
 @frappe.whitelist()
-def get_all_sales_partner(from_date, company, field, limit = None):
+def get_all_sales_partner(date_range, company, field, limit = None):
 	if field == "total_sales_amount":
 		select_field = "sum(`base_net_total`)"
 	elif field == "total_commission":
@@ -154,8 +163,9 @@
 		'docstatus': 1,
 		'company': company
 	}
-	if from_date:
-		filters['transaction_date'] = ['>=', from_date]
+	if date_range:
+		date_range = frappe.parse_json(date_range)
+		filters['transaction_date'] = ['between', [date_range[0], date_range[1]]]
 
 	return frappe.get_list('Sales Order', fields=[
 		'`sales_partner` as name',
@@ -163,15 +173,27 @@
 	], filters=filters, group_by='sales_partner', order_by='value DESC', limit=limit)
 
 @frappe.whitelist()
-def get_all_sales_person(from_date, company, field = None, limit = 0):
+def get_all_sales_person(date_range, company, field = None, limit = 0):
+	date_condition = get_date_condition(date_range, 'sales_order.transaction_date')
+
 	return frappe.db.sql("""
 		select sales_team.sales_person as name, sum(sales_order.base_net_total) as value
 		from `tabSales Order` as sales_order join `tabSales Team` as sales_team
 			on sales_order.name = sales_team.parent and sales_team.parenttype = 'Sales Order'
 		where sales_order.docstatus = 1
-			and sales_order.transaction_date >= %s
 			and sales_order.company = %s
+			{date_condition}
 		group by sales_team.sales_person
 		order by value DESC
 		limit %s
-	""", (from_date, company, cint(limit)), as_dict=1)
+	""".format(date_condition=date_condition), (company, cint(limit)), as_dict=1)
+
+def get_date_condition(date_range, field):
+	date_condition = ''
+	if date_range:
+		date_range = frappe.parse_json(date_range)
+		from_date, to_date = date_range
+		date_condition = "and {0} between {1} and {2}".format(
+			field, frappe.db.escape(from_date), frappe.db.escape(to_date)
+		)
+	return date_condition
\ No newline at end of file
diff --git a/erpnext/stock/dashboard_chart/delivery_trends/delivery_trends.json b/erpnext/stock/dashboard_chart/delivery_trends/delivery_trends.json
new file mode 100644
index 0000000..b3f6e35
--- /dev/null
+++ b/erpnext/stock/dashboard_chart/delivery_trends/delivery_trends.json
@@ -0,0 +1,27 @@
+{
+ "based_on": "posting_date",
+ "chart_name": "Delivery Trends",
+ "chart_type": "Sum",
+ "color": "#4d4da8",
+ "creation": "2020-07-20 21:01:04.255291",
+ "docstatus": 0,
+ "doctype": "Dashboard Chart",
+ "document_type": "Delivery Note",
+ "filters_json": "[[\"Delivery Note\",\"docstatus\",\"=\",1]]",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "modified": "2020-07-22 13:03:24.937045",
+ "modified_by": "Administrator",
+ "module": "Stock",
+ "name": "Delivery Trends",
+ "number_of_groups": 0,
+ "owner": "Administrator",
+ "time_interval": "Monthly",
+ "timeseries": 1,
+ "timespan": "Last Year",
+ "type": "Bar",
+ "use_report_chart": 0,
+ "value_based_on": "base_net_total",
+ "y_axis": []
+}
\ No newline at end of file
diff --git a/erpnext/stock/dashboard_chart/item_shortage_summary/item_shortage_summary.json b/erpnext/stock/dashboard_chart/item_shortage_summary/item_shortage_summary.json
new file mode 100644
index 0000000..ce71124
--- /dev/null
+++ b/erpnext/stock/dashboard_chart/item_shortage_summary/item_shortage_summary.json
@@ -0,0 +1,23 @@
+{
+ "chart_name": "Item Shortage Summary",
+ "chart_type": "Report",
+ "creation": "2020-07-20 21:01:04.383451",
+ "docstatus": 0,
+ "doctype": "Dashboard Chart",
+ "dynamic_filters_json": "{\"company\":\"frappe.defaults.get_user_default(\\\"Company\\\")\"}",
+ "filters_json": "{}",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "modified": "2020-07-22 13:07:01.905334",
+ "modified_by": "Administrator",
+ "module": "Stock",
+ "name": "Item Shortage Summary",
+ "number_of_groups": 0,
+ "owner": "Administrator",
+ "report_name": "Item Shortage Report",
+ "timeseries": 0,
+ "type": "Bar",
+ "use_report_chart": 1,
+ "y_axis": []
+}
\ No newline at end of file
diff --git a/erpnext/stock/dashboard_chart/oldest_items/oldest_items.json b/erpnext/stock/dashboard_chart/oldest_items/oldest_items.json
new file mode 100644
index 0000000..6da3b28
--- /dev/null
+++ b/erpnext/stock/dashboard_chart/oldest_items/oldest_items.json
@@ -0,0 +1,24 @@
+{
+ "chart_name": "Oldest Items",
+ "chart_type": "Report",
+ "creation": "2020-07-20 21:01:04.336845",
+ "custom_options": "{\"colors\": [\"#5e64ff\"]}",
+ "docstatus": 0,
+ "doctype": "Dashboard Chart",
+ "dynamic_filters_json": "{\"company\":\"frappe.defaults.get_user_default(\\\"Company\\\")\",\"to_date\":\"frappe.datetime.nowdate()\"}",
+ "filters_json": "{\"show_warehouse_wise_stock\":0}",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "modified": "2020-07-22 13:04:36.271198",
+ "modified_by": "Administrator",
+ "module": "Stock",
+ "name": "Oldest Items",
+ "number_of_groups": 0,
+ "owner": "Administrator",
+ "report_name": "Stock Ageing",
+ "timeseries": 0,
+ "type": "Bar",
+ "use_report_chart": 1,
+ "y_axis": []
+}
\ No newline at end of file
diff --git a/erpnext/stock/dashboard_chart/purchase_receipt_trends/purchase_receipt_trends.json b/erpnext/stock/dashboard_chart/purchase_receipt_trends/purchase_receipt_trends.json
new file mode 100644
index 0000000..584a6cc
--- /dev/null
+++ b/erpnext/stock/dashboard_chart/purchase_receipt_trends/purchase_receipt_trends.json
@@ -0,0 +1,27 @@
+{
+ "based_on": "posting_date",
+ "chart_name": "Purchase Receipt Trends",
+ "chart_type": "Sum",
+ "color": "#78d6ff",
+ "creation": "2020-07-20 21:01:04.205230",
+ "docstatus": 0,
+ "doctype": "Dashboard Chart",
+ "document_type": "Purchase Receipt",
+ "filters_json": "[[\"Purchase Receipt\",\"docstatus\",\"=\",1]]",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "modified": "2020-07-22 13:05:25.923130",
+ "modified_by": "Administrator",
+ "module": "Stock",
+ "name": "Purchase Receipt Trends",
+ "number_of_groups": 0,
+ "owner": "Administrator",
+ "time_interval": "Monthly",
+ "timeseries": 1,
+ "timespan": "Last Year",
+ "type": "Bar",
+ "use_report_chart": 0,
+ "value_based_on": "base_net_total",
+ "y_axis": []
+}
\ No newline at end of file
diff --git a/erpnext/stock/dashboard_chart/warehouse_wise_stock_value/warehouse_wise_stock_value.json b/erpnext/stock/dashboard_chart/warehouse_wise_stock_value/warehouse_wise_stock_value.json
new file mode 100644
index 0000000..a07b553
--- /dev/null
+++ b/erpnext/stock/dashboard_chart/warehouse_wise_stock_value/warehouse_wise_stock_value.json
@@ -0,0 +1,22 @@
+{
+ "chart_name": "Warehouse wise Stock Value",
+ "chart_type": "Custom",
+ "creation": "2020-07-20 21:01:04.296157",
+ "docstatus": 0,
+ "doctype": "Dashboard Chart",
+ "filters_json": "{}",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "modified": "2020-07-22 13:01:01.815123",
+ "modified_by": "Administrator",
+ "module": "Stock",
+ "name": "Warehouse wise Stock Value",
+ "number_of_groups": 0,
+ "owner": "Administrator",
+ "source": "Warehouse wise Stock Value",
+ "timeseries": 0,
+ "type": "Bar",
+ "use_report_chart": 0,
+ "y_axis": []
+}
\ No newline at end of file
diff --git a/erpnext/stock/dashboard_fixtures.py b/erpnext/stock/dashboard_fixtures.py
deleted file mode 100644
index 7625b1a..0000000
--- a/erpnext/stock/dashboard_fixtures.py
+++ /dev/null
@@ -1,170 +0,0 @@
-# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-import frappe
-import json
-from frappe import _
-from frappe.utils import nowdate
-from erpnext.accounts.dashboard_fixtures import _get_fiscal_year
-from erpnext.buying.dashboard_fixtures import get_company_for_dashboards
-
-def get_data():
-	fiscal_year = _get_fiscal_year(nowdate())
-
-	if not fiscal_year:
-		return frappe._dict()
-
-	company = frappe.get_doc("Company", get_company_for_dashboards())
-	fiscal_year_name = fiscal_year.get("name")
-	start_date = str(fiscal_year.get("year_start_date"))
-	end_date = str(fiscal_year.get("year_end_date"))
-
-	return frappe._dict({
-		"dashboards": get_dashboards(),
-		"charts": get_charts(company, fiscal_year_name, start_date, end_date),
-		"number_cards": get_number_cards(company, fiscal_year_name, start_date, end_date),
-	})
-
-def get_dashboards():
-	return [{
-		"name": "Stock",
-		"dashboard_name": "Stock",
-		"charts": [
-			{ "chart": "Warehouse wise Stock Value", "width": "Full"},
-			{ "chart": "Purchase Receipt Trends", "width": "Half"},
-			{ "chart": "Delivery Trends", "width": "Half"},
-			{ "chart": "Oldest Items", "width": "Half"},
-			{ "chart": "Item Shortage Summary", "width": "Half"}
-		],
-		"cards": [
-			{ "card": "Total Active Items"},
-			{ "card": "Total Warehouses"},
-			{ "card": "Total Stock Value"}
-		]
-	}]
-
-def get_charts(company, fiscal_year_name, start_date, end_date):
-	return [
-		{
-			"doctype": "Dashboard Chart",
-			"name": "Purchase Receipt Trends",
-			"time_interval": "Monthly",
-			"chart_name": _("Purchase Receipt Trends"),
-			"timespan": "Last Year",
-			"color": "#7b933d",
-			"value_based_on": "base_net_total",
-			"filters_json": json.dumps([["Purchase Receipt", "docstatus", "=", 1]]),
-			"chart_type": "Sum",
-			"timeseries": 1,
-			"based_on": "posting_date",
-			"owner": "Administrator",
-			"document_type": "Purchase Receipt",
-			"type": "Bar",
-			"width": "Half",
-			"is_public": 1
-		},
-		{
-			"doctype": "Dashboard Chart",
-			"name": "Delivery Trends",
-			"time_interval": "Monthly",
-			"chart_name": _("Delivery Trends"),
-			"timespan": "Last Year",
-			"color": "#7b933d",
-			"value_based_on": "base_net_total",
-			"filters_json": json.dumps([["Delivery Note", "docstatus", "=", 1]]),
-			"chart_type": "Sum",
-			"timeseries": 1,
-			"based_on": "posting_date",
-			"owner": "Administrator",
-			"document_type": "Delivery Note",
-			"type": "Bar",
-			"width": "Half",
-			"is_public": 1
-		},
-		{
-			"name": "Warehouse wise Stock Value",
-			"chart_name": _("Warehouse wise Stock Value"),
-			"chart_type": "Custom",
-			"doctype": "Dashboard Chart",
-			"filters_json": json.dumps({}),
-			"is_custom": 0,
-			"is_public": 1,
-			"owner": "Administrator",
-			"source": "Warehouse wise Stock Value",
-			"type": "Bar"
-		},
-		{
-			"name": "Oldest Items",
-			"chart_name": _("Oldest Items"),
-			"chart_type": "Report",
-			"custom_options": json.dumps({
-				"colors": ["#5e64ff"]
-				}),
-			"doctype": "Dashboard Chart",
-			"filters_json": json.dumps({
-				"company": company.name,
-				"to_date": nowdate(),
-				"show_warehouse_wise_stock": 0
-			}),
-			"is_custom": 1,
-			"is_public": 1,
-			"owner": "Administrator",
-			"report_name": "Stock Ageing",
-			"type": "Bar"
-		},
-		{
-			"name": "Item Shortage Summary",
-			"chart_name": _("Item Shortage Summary"),
-			"chart_type": "Report",
-			"doctype": "Dashboard Chart",
-			"filters_json": json.dumps({
-				"company": company.name
-			}),
-			"is_custom": 1,
-			"is_public": 1,
-			"owner": "Administrator",
-			"report_name": "Item Shortage Report",
-			"type": "Bar"
-		}
-	]
-
-def get_number_cards(company, fiscal_year_name, start_date, end_date):
-	return [
-		{
-			"name": "Total Active Items",
-			"label": _("Total Active Items"),
-			"function": "Count",
-			"doctype": "Number Card",
-			"document_type": "Item",
-			"filters_json": json.dumps([["Item", "disabled", "=", 0]]),
-			"is_public": 1,
-			"owner": "Administrator",
-			"show_percentage_stats": 1,
-			"stats_time_interval": "Monthly"
-		},
-		{
-			"name": "Total Warehouses",
-			"label": _("Total Warehouses"),
-			"function": "Count",
-			"doctype": "Number Card",
-			"document_type": "Warehouse",
-			"filters_json": json.dumps([["Warehouse", "disabled", "=", 0]]),
-			"is_public": 1,
-			"owner": "Administrator",
-			"show_percentage_stats": 1,
-			"stats_time_interval": "Monthly"
-		},
-		{
-			"name": "Total Stock Value",
-			"label": _("Total Stock Value"),
-			"function": "Sum",
-			"aggregate_function_based_on": "stock_value",
-			"doctype": "Number Card",
-			"document_type": "Bin",
-			"filters_json": json.dumps([]),
-			"is_public": 1,
-			"owner": "Administrator",
-			"show_percentage_stats": 1,
-			"stats_time_interval": "Daily"
-		}
-	]
\ No newline at end of file
diff --git a/erpnext/stock/doctype/batch/batch.py b/erpnext/stock/doctype/batch/batch.py
index a091ac7..c8424f1 100644
--- a/erpnext/stock/doctype/batch/batch.py
+++ b/erpnext/stock/doctype/batch/batch.py
@@ -143,7 +143,7 @@
 
 
 @frappe.whitelist()
-def get_batch_qty(batch_no=None, warehouse=None, item_code=None):
+def get_batch_qty(batch_no=None, warehouse=None, item_code=None, posting_date=None, posting_time=None):
 	"""Returns batch actual qty if warehouse is passed,
 		or returns dict of qty by warehouse if warehouse is None
 
@@ -155,9 +155,14 @@
 
 	out = 0
 	if batch_no and warehouse:
+		cond = ""
+		if posting_date and posting_time:
+			cond = " and timestamp(posting_date, posting_time) <= timestamp('{0}', '{1}')".format(posting_date,
+				posting_time)
+
 		out = float(frappe.db.sql("""select sum(actual_qty)
 			from `tabStock Ledger Entry`
-			where warehouse=%s and batch_no=%s""",
+			where warehouse=%s and batch_no=%s {0}""".format(cond),
 			(warehouse, batch_no))[0][0] or 0)
 
 	if batch_no and not warehouse:
diff --git a/erpnext/stock/doctype/customs_tariff_number/customs_tariff_number.json b/erpnext/stock/doctype/customs_tariff_number/customs_tariff_number.json
index 07992b8..7eeb147 100644
--- a/erpnext/stock/doctype/customs_tariff_number/customs_tariff_number.json
+++ b/erpnext/stock/doctype/customs_tariff_number/customs_tariff_number.json
@@ -71,7 +71,7 @@
    "read_only": 0, 
    "remember_last_selected_value": 0, 
    "report_hide": 0, 
-   "reqd": 1, 
+   "reqd": 0, 
    "search_index": 0, 
    "set_only_once": 0, 
    "translatable": 0, 
@@ -88,7 +88,7 @@
  "issingle": 0, 
  "istable": 0, 
  "max_attachments": 0, 
- "modified": "2018-09-12 09:30:03.951743", 
+ "modified": "2020-06-26 09:30:03.951743", 
  "modified_by": "Administrator", 
  "module": "Stock", 
  "name": "Customs Tariff Number", 
@@ -143,4 +143,4 @@
  "track_changes": 1, 
  "track_seen": 0, 
  "track_views": 0
-}
\ No newline at end of file
+}
diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.json b/erpnext/stock/doctype/delivery_note/delivery_note.json
index 84d2057..66efcf8 100644
--- a/erpnext/stock/doctype/delivery_note/delivery_note.json
+++ b/erpnext/stock/doctype/delivery_note/delivery_note.json
@@ -801,6 +801,7 @@
    "fieldname": "base_in_words",
    "fieldtype": "Data",
    "label": "In Words (Company Currency)",
+   "length": 240,
    "oldfieldname": "in_words",
    "oldfieldtype": "Data",
    "print_hide": 1,
@@ -851,6 +852,7 @@
    "fieldname": "in_words",
    "fieldtype": "Data",
    "label": "In Words",
+   "length": 240,
    "oldfieldname": "in_words_export",
    "oldfieldtype": "Data",
    "print_hide": 1,
@@ -1253,7 +1255,7 @@
  "idx": 146,
  "is_submittable": 1,
  "links": [],
- "modified": "2020-05-19 17:03:45.880106",
+ "modified": "2020-07-18 05:13:55.580420",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Delivery Note",
diff --git a/erpnext/stock/doctype/delivery_note/test_delivery_note.py b/erpnext/stock/doctype/delivery_note/test_delivery_note.py
index a921a56..4b04a0a 100644
--- a/erpnext/stock/doctype/delivery_note/test_delivery_note.py
+++ b/erpnext/stock/doctype/delivery_note/test_delivery_note.py
@@ -537,11 +537,8 @@
 		dt = make_delivery_trip(dn.name)
 		self.assertEqual(dn.name, dt.delivery_stops[0].delivery_note)
 
-	def test_delivery_note_for_enable_allow_cost_center_in_entry_of_bs_account(self):
+	def test_delivery_note_with_cost_center(self):
 		from erpnext.accounts.doctype.cost_center.test_cost_center import create_cost_center
-		accounts_settings = frappe.get_doc('Accounts Settings', 'Accounts Settings')
-		accounts_settings.allow_cost_center_in_entry_of_bs_account = 1
-		accounts_settings.save()
 		cost_center = "_Test Cost Center for BS Account - TCP1"
 		create_cost_center(cost_center_name="_Test Cost Center for BS Account", company="_Test Company with perpetual inventory")
 
@@ -567,13 +564,8 @@
 		}
 		for i, gle in enumerate(gl_entries):
 			self.assertEqual(expected_values[gle.account]["cost_center"], gle.cost_center)
-		accounts_settings.allow_cost_center_in_entry_of_bs_account = 0
-		accounts_settings.save()
 
-	def test_delivery_note_for_disable_allow_cost_center_in_entry_of_bs_account(self):
-		accounts_settings = frappe.get_doc('Accounts Settings', 'Accounts Settings')
-		accounts_settings.allow_cost_center_in_entry_of_bs_account = 0
-		accounts_settings.save()
+	def test_delivery_note_cost_center_with_balance_sheet_account(self):
 		cost_center = "Main - TCP1"
 
 		company = frappe.db.get_value('Warehouse', 'Stores - TCP1', 'company')
@@ -583,7 +575,11 @@
 		make_stock_entry(target="Stores - TCP1", qty=5, basic_rate=100)
 
 		stock_in_hand_account = get_inventory_account('_Test Company with perpetual inventory')
-		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",
+			do_not_submit=1)
+
+		dn.get('items')[0].cost_center = None
+		dn.submit()
 
 		gl_entries = get_gl_entries("Delivery Note", dn.name)
 
@@ -593,7 +589,7 @@
 				"cost_center": cost_center
 			},
 			stock_in_hand_account: {
-				"cost_center": None
+				"cost_center": cost_center
 			}
 		}
 		for i, gle in enumerate(gl_entries):
diff --git a/erpnext/stock/doctype/delivery_note_item/delivery_note_item.json b/erpnext/stock/doctype/delivery_note_item/delivery_note_item.json
index 7ea2de2..3d57f47 100644
--- a/erpnext/stock/doctype/delivery_note_item/delivery_note_item.json
+++ b/erpnext/stock/doctype/delivery_note_item/delivery_note_item.json
@@ -1,5 +1,4 @@
 {
- "actions": [],
  "autoname": "hash",
  "creation": "2013-04-22 13:15:44",
  "doctype": "DocType",
@@ -82,6 +81,7 @@
   "accounting_dimensions_section",
   "cost_center",
   "dimension_col_break",
+  "project",
   "section_break_72",
   "page_break"
  ],
@@ -702,6 +702,12 @@
    "fieldtype": "Column Break"
   },
   {
+   "fieldname": "project",
+   "fieldtype": "Link",
+   "label": "Project",
+   "options": "Project"
+  },
+  {
    "fieldname": "dn_detail",
    "fieldtype": "Data",
    "hidden": 1,
@@ -714,7 +720,7 @@
  "idx": 1,
  "istable": 1,
  "links": [],
- "modified": "2020-03-05 14:18:33.131672",
+ "modified": "2020-07-20 12:25:06.177894",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Delivery Note Item",
diff --git a/erpnext/stock/doctype/item/item.json b/erpnext/stock/doctype/item/item.json
index c371999..963c87a 100644
--- a/erpnext/stock/doctype/item/item.json
+++ b/erpnext/stock/doctype/item/item.json
@@ -987,6 +987,7 @@
    "read_only": 1
   },
   {
+   "collapsible": 1,
    "depends_on": "eval:(!doc.is_item_from_hub)",
    "fieldname": "hub_publishing_sb",
    "fieldtype": "Section Break",
@@ -1060,7 +1061,7 @@
  "image_field": "image",
  "links": [],
  "max_attachments": 1,
- "modified": "2020-04-08 15:56:06.195722",
+ "modified": "2020-06-30 12:01:07.534447",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Item",
@@ -1122,4 +1123,4 @@
  "sort_order": "DESC",
  "title_field": "item_name",
  "track_changes": 1
-}
+}
\ No newline at end of file
diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py
index 3436a5d..d5f479f 100644
--- a/erpnext/stock/doctype/item/item.py
+++ b/erpnext/stock/doctype/item/item.py
@@ -13,7 +13,7 @@
 from erpnext.setup.doctype.item_group.item_group import (get_parent_item_groups, invalidate_cache_for)
 from frappe import _, msgprint
 from frappe.utils import (cint, cstr, flt, formatdate, get_timestamp, getdate,
-						  now_datetime, random_string, strip)
+						  now_datetime, random_string, strip, get_link_to_form)
 from frappe.utils.html_utils import clean_html
 from frappe.website.doctype.website_slideshow.website_slideshow import \
 	get_slideshow
@@ -597,7 +597,7 @@
 	def stock_ledger_created(self):
 		if not hasattr(self, '_stock_ledger_created'):
 			self._stock_ledger_created = len(frappe.db.sql("""select name from `tabStock Ledger Entry`
-				where item_code = %s limit 1""", self.name))
+				where item_code = %s and is_cancelled = 0 limit 1""", self.name))
 		return self._stock_ledger_created
 
 	def validate_name_with_item_group(self):
@@ -634,6 +634,9 @@
 									+ ": \n" + ", ".join([self.meta.get_label(fld) for fld in field_list]))
 
 	def after_rename(self, old_name, new_name, merge):
+		if merge:
+			self.validate_duplicate_item_in_stock_reconciliation(old_name, new_name)
+
 		if self.route:
 			invalidate_cache_for_item(self)
 			clear_cache(self.route)
@@ -656,6 +659,27 @@
 					frappe.db.set_value(dt, d.name, "item_wise_tax_detail",
 											json.dumps(item_wise_tax_detail), update_modified=False)
 
+	def validate_duplicate_item_in_stock_reconciliation(self, old_name, new_name):
+		records = frappe.db.sql(""" SELECT parent, COUNT(*) as records
+			FROM `tabStock Reconciliation Item`
+			WHERE item_code = %s and docstatus = 1
+			GROUP By item_code, warehouse, parent
+			HAVING records > 1
+		""", new_name, as_dict=1)
+
+		if not records: return
+		document = _("Stock Reconciliation") if len(records) == 1 else _("Stock Reconciliations")
+
+		msg = _("The items {0} and {1} are present in the following {2} : <br>"
+			.format(frappe.bold(old_name), frappe.bold(new_name), document))
+
+		msg += ', '.join([get_link_to_form("Stock Reconciliation", d.parent) for d in records]) + "<br><br>"
+
+		msg += _("Note: To merge the items, create a separate Stock Reconciliation for the old item {0}"
+			.format(frappe.bold(old_name)))
+
+		frappe.throw(_(msg), title=_("Merge not allowed"))
+
 	def set_last_purchase_rate(self, new_name):
 		last_purchase_rate = get_last_purchase_details(new_name).get("base_net_rate", 0)
 		frappe.db.set_value("Item", new_name, "last_purchase_rate", last_purchase_rate)
@@ -883,7 +907,12 @@
 			linked_doctypes += ["Sales Order Item", "Purchase Order Item", "Material Request Item"]
 
 		for doctype in linked_doctypes:
-			if frappe.db.get_value(doctype, filters={"item_code": self.name, "docstatus": 1}) or \
+			if doctype in ("Purchase Invoice Item", "Sales Invoice Item",):
+				# If Invoice has Stock impact, only then consider it.
+				if self.stock_ledger_created():
+					return True
+
+			elif frappe.db.get_value(doctype, filters={"item_code": self.name, "docstatus": 1}) or \
 				frappe.db.get_value("Production Order",
 					filters={"production_item": self.name, "docstatus": 1}):
 				return True
diff --git a/erpnext/stock/doctype/item/test_records.json b/erpnext/stock/doctype/item/test_records.json
index 6c1a559..9ca887c 100644
--- a/erpnext/stock/doctype/item/test_records.json
+++ b/erpnext/stock/doctype/item/test_records.json
@@ -92,8 +92,7 @@
    {
     "doctype": "Item Tax",
     "parentfield": "taxes",
-    "item_tax_template": "_Test Account Excise Duty @ 10",
-    "tax_category": ""
+    "item_tax_template": "_Test Account Excise Duty @ 10"
    }
   ],
   "stock_uom": "_Test UOM 1"
@@ -371,8 +370,7 @@
    {
     "doctype": "Item Tax",
     "parentfield": "taxes",
-    "item_tax_template": "_Test Account Excise Duty @ 10",
-    "tax_category": ""
+    "item_tax_template": "_Test Account Excise Duty @ 10"
    },
    {
     "doctype": "Item Tax",
@@ -451,14 +449,13 @@
    {
     "doctype": "Item Tax",
     "parentfield": "taxes",
-    "item_tax_template": "_Test Account Excise Duty @ 20",
-    "tax_category": ""
+    "item_tax_template": "_Test Account Excise Duty @ 20"
    },
    {
     "doctype": "Item Tax",
     "parentfield": "taxes",
-    "item_tax_template": "_Test Item Tax Template 1",
-    "tax_category": "_Test Tax Category 1"
+    "tax_category": "_Test Tax Category 1",
+    "item_tax_template": "_Test Item Tax Template 1"
    }
   ]
  }
diff --git a/erpnext/stock/doctype/item_alternative/item_alternative.py b/erpnext/stock/doctype/item_alternative/item_alternative.py
index da0c3b7..522dfc6 100644
--- a/erpnext/stock/doctype/item_alternative/item_alternative.py
+++ b/erpnext/stock/doctype/item_alternative/item_alternative.py
@@ -42,6 +42,7 @@
 			'alternative_item_code': self.alternative_item_code, 'name': ('!=', self.name)}):
 			frappe.throw(_("Already record exists for the item {0}").format(self.item_code))
 
+@frappe.whitelist()
 def get_alternative_items(doctype, txt, searchfield, start, page_len, filters):
 	return frappe.db.sql(""" (select alternative_item_code from `tabItem Alternative`
 			where item_code = %(item_code)s and alternative_item_code like %(txt)s)
@@ -52,4 +53,4 @@
 		""".format(start, page_len), {
 			"item_code": filters.get('item_code'),
 			"txt": '%' + txt + '%'
-		})
\ No newline at end of file
+		})
diff --git a/erpnext/stock/doctype/item_price/item_price.json b/erpnext/stock/doctype/item_price/item_price.json
index 2e0ddfd..5f62381 100644
--- a/erpnext/stock/doctype/item_price/item_price.json
+++ b/erpnext/stock/doctype/item_price/item_price.json
@@ -172,7 +172,7 @@
    "default": "Today",
    "fieldname": "valid_from",
    "fieldtype": "Date",
-   "label": "Valid From "
+   "label": "Valid From"
   },
   {
    "default": "0",
@@ -187,7 +187,7 @@
   {
    "fieldname": "valid_upto",
    "fieldtype": "Date",
-   "label": "Valid Upto "
+   "label": "Valid Upto"
   },
   {
    "fieldname": "section_break_24",
@@ -208,7 +208,7 @@
  "icon": "fa fa-flag",
  "idx": 1,
  "links": [],
- "modified": "2020-02-28 14:21:25.580331",
+ "modified": "2020-07-06 22:31:32.943475",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Item Price",
diff --git a/erpnext/stock/doctype/item_tax/item_tax.json b/erpnext/stock/doctype/item_tax/item_tax.json
index a93e463..ae36efc 100644
--- a/erpnext/stock/doctype/item_tax/item_tax.json
+++ b/erpnext/stock/doctype/item_tax/item_tax.json
@@ -1,5 +1,4 @@
 {
- "actions": [],
  "creation": "2013-02-22 01:28:01",
  "doctype": "DocType",
  "editable_grid": 1,
@@ -38,8 +37,7 @@
  ],
  "idx": 1,
  "istable": 1,
- "links": [],
- "modified": "2019-12-28 21:54:40.807849",
+ "modified": "2020-06-25 01:40:28.859752",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Item Tax",
diff --git a/erpnext/stock/doctype/material_request/material_request.js b/erpnext/stock/doctype/material_request/material_request.js
index 3a8deb6..3c4e353 100644
--- a/erpnext/stock/doctype/material_request/material_request.js
+++ b/erpnext/stock/doctype/material_request/material_request.js
@@ -49,17 +49,21 @@
 		// set schedule_date
 		set_schedule_date(frm);
 
-		let filters = {'company': frm.doc.company}
-
-		frm.set_query("warehouse", "items", function() {
+		frm.set_query("warehouse", "items", function(doc) {
 			return {
-				filters: filters
+				filters: {'company': doc.company}
 			};
 		});
 
-		frm.set_query("set_warehouse", function(){
+		frm.set_query("set_warehouse", function(doc){
 			return {
-				filters: filters
+				filters: {'company': doc.company}
+			};
+		});
+
+		frm.set_query("set_from_warehouse", function(doc){
+			return {
+				filters: {'company': doc.company}
 			};
 		});
 	},
@@ -180,9 +184,8 @@
 		});
 	},
 
-	get_item_data: function(frm, item) {
+	get_item_data: function(frm, item, overwrite_warehouse=false) {
 		if (item && !item.item_code) { return; }
-
 		frm.call({
 			method: "erpnext.stock.get_item_details.get_item_details",
 			child: item,
@@ -203,7 +206,8 @@
 					plc_conversion_rate: 1,
 					rate: item.rate,
 					conversion_factor: item.conversion_factor
-				}
+				},
+				overwrite_warehouse: overwrite_warehouse
 			},
 			callback: function(r) {
 				const d = item;
@@ -354,29 +358,29 @@
 		}
 
 		const item = locals[doctype][name];
-		frm.events.get_item_data(frm, item);
+		frm.events.get_item_data(frm, item, false);
 	},
 
 	from_warehouse: function(frm, doctype, name) {
 		const item = locals[doctype][name];
-		frm.events.get_item_data(frm, item);
+		frm.events.get_item_data(frm, item, false);
 	},
 
 	warehouse: function(frm, doctype, name) {
 		const item = locals[doctype][name];
-		frm.events.get_item_data(frm, item);
+		frm.events.get_item_data(frm, item, false);
 	},
 
 	rate: function(frm, doctype, name) {
 		const item = locals[doctype][name];
-		frm.events.get_item_data(frm, item);
+		frm.events.get_item_data(frm, item, false);
 	},
 
 	item_code: function(frm, doctype, name) {
 		const item = locals[doctype][name];
 		item.rate = 0;
 		set_schedule_date(frm);
-		frm.events.get_item_data(frm, item);
+		frm.events.get_item_data(frm, item, true);
 	},
 
 	schedule_date: function(frm, cdt, cdn) {
diff --git a/erpnext/stock/doctype/material_request/material_request.py b/erpnext/stock/doctype/material_request/material_request.py
index 97606f4..25f1ed9 100644
--- a/erpnext/stock/doctype/material_request/material_request.py
+++ b/erpnext/stock/doctype/material_request/material_request.py
@@ -402,6 +402,7 @@
 
 	return material_requests
 
+@frappe.whitelist()
 def get_default_supplier_query(doctype, txt, searchfield, start, page_len, filters):
 	doc = frappe.get_doc("Material Request", filters.get("doc"))
 	item_list = []
@@ -567,4 +568,4 @@
 
 	doc.set_item_locations()
 
-	return doc
\ No newline at end of file
+	return doc
diff --git a/erpnext/stock/doctype/packing_slip/packing_slip.py b/erpnext/stock/doctype/packing_slip/packing_slip.py
index 7a5ae31..4f831d7 100644
--- a/erpnext/stock/doctype/packing_slip/packing_slip.py
+++ b/erpnext/stock/doctype/packing_slip/packing_slip.py
@@ -175,6 +175,7 @@
 
 		self.update_item_details()
 
+@frappe.whitelist()
 def item_details(doctype, txt, searchfield, start, page_len, filters):
 	from erpnext.controllers.queries import get_match_cond
 	return frappe.db.sql("""select name, item_name, description from `tabItem`
diff --git a/erpnext/stock/doctype/pick_list/pick_list.js b/erpnext/stock/doctype/pick_list/pick_list.js
index 3a5ef76..ee218f2 100644
--- a/erpnext/stock/doctype/pick_list/pick_list.js
+++ b/erpnext/stock/doctype/pick_list/pick_list.js
@@ -3,6 +3,9 @@
 
 frappe.ui.form.on('Pick List', {
 	setup: (frm) => {
+		frm.set_indicator_formatter('item_code',
+			function(doc) { return (doc.stock_qty === 0) ? "red" : "green"; });
+
 		frm.custom_make_buttons = {
 			'Delivery Note': 'Delivery Note',
 			'Stock Entry': 'Stock Entry',
diff --git a/erpnext/stock/doctype/pick_list/pick_list.py b/erpnext/stock/doctype/pick_list/pick_list.py
index 4b8b594..0da57b7 100644
--- a/erpnext/stock/doctype/pick_list/pick_list.py
+++ b/erpnext/stock/doctype/pick_list/pick_list.py
@@ -26,11 +26,12 @@
 				continue
 			if not item.serial_no:
 				frappe.throw(_("Row #{0}: {1} does not have any available serial numbers in {2}".format(
-					frappe.bold(item.idx), frappe.bold(item.item_code), frappe.bold(item.warehouse))))
+					frappe.bold(item.idx), frappe.bold(item.item_code), frappe.bold(item.warehouse))),
+					title=_("Serial Nos Required"))
 			if len(item.serial_no.split('\n')) == item.picked_qty:
 				continue
 			frappe.throw(_('For item {0} at row {1}, count of serial numbers does not match with the picked quantity')
-				.format(frappe.bold(item.item_code), frappe.bold(item.idx)))
+				.format(frappe.bold(item.item_code), frappe.bold(item.idx)), title=_("Quantity Mismatch"))
 
 	def set_item_locations(self, save=False):
 		items = self.aggregate_item_qty()
@@ -40,6 +41,9 @@
 		if self.parent_warehouse:
 			from_warehouses = frappe.db.get_descendants('Warehouse', self.parent_warehouse)
 
+		# Create replica before resetting, to handle empty table on update after submit.
+		locations_replica  = self.get('locations')
+
 		# reset
 		self.delete_key('locations')
 		for item_doc in items:
@@ -48,7 +52,7 @@
 			self.item_location_map.setdefault(item_code,
 				get_available_item_locations(item_code, from_warehouses, self.item_count_map.get(item_code), self.company))
 
-			locations = get_items_with_location_and_quantity(item_doc, self.item_location_map)
+			locations = get_items_with_location_and_quantity(item_doc, self.item_location_map, self.docstatus)
 
 			item_doc.idx = None
 			item_doc.name = None
@@ -62,6 +66,16 @@
 				location.update(row)
 				self.append('locations', location)
 
+		# If table is empty on update after submit, set stock_qty, picked_qty to 0 so that indicator is red
+		# and give feedback to the user. This is to avoid empty Pick Lists.
+		if not self.get('locations') and self.docstatus == 1:
+			for location in locations_replica:
+				location.stock_qty = 0
+				location.picked_qty = 0
+				self.append('locations', location)
+			frappe.msgprint(_("Please Restock Items and Update the Pick List to continue. To discontinue, cancel the Pick List."),
+				 title=_("Out of Stock"), indicator="red")
+
 		if save:
 			self.save()
 
@@ -97,11 +111,13 @@
 	if not pick_list.locations:
 		frappe.throw(_("Add items in the Item Locations table"))
 
-def get_items_with_location_and_quantity(item_doc, item_location_map):
+def get_items_with_location_and_quantity(item_doc, item_location_map, docstatus):
 	available_locations = item_location_map.get(item_doc.item_code)
 	locations = []
 
-	remaining_stock_qty = item_doc.stock_qty
+	# if stock qty is zero on submitted entry, show positive remaining qty to recalculate in case of restock.
+	remaining_stock_qty = item_doc.qty if (docstatus == 1 and item_doc.stock_qty == 0) else item_doc.stock_qty
+
 	while remaining_stock_qty > 0 and available_locations:
 		item_location = available_locations.pop(0)
 		item_location = frappe._dict(item_location)
@@ -119,13 +135,11 @@
 		if item_location.serial_no:
 			serial_nos = '\n'.join(item_location.serial_no[0: cint(stock_qty)])
 
-		auto_set_serial_no = frappe.db.get_single_value("Stock Settings", "automatically_set_serial_nos_based_on_fifo")
-
 		locations.append(frappe._dict({
 			'qty': qty,
 			'stock_qty': stock_qty,
 			'warehouse': item_location.warehouse,
-			'serial_no': serial_nos if auto_set_serial_no else item_doc.serial_no,
+			'serial_no': serial_nos,
 			'batch_no': item_location.batch_no
 		}))
 
@@ -137,7 +151,7 @@
 			item_location.qty = qty_diff
 			if item_location.serial_no:
 				# set remaining serial numbers
-				item_location.serial_no = item_location.serial_no[-qty_diff:]
+				item_location.serial_no = item_location.serial_no[-int(qty_diff):]
 			available_locations = [item_location] + available_locations
 
 	# update available locations for the item
@@ -146,9 +160,14 @@
 
 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'):
+	has_serial_no  = frappe.get_cached_value('Item', item_code, 'has_serial_no')
+	has_batch_no = frappe.get_cached_value('Item', item_code, 'has_batch_no')
+
+	if has_batch_no and has_serial_no:
+		locations = get_available_item_locations_for_serial_and_batched_item(item_code, from_warehouses, required_qty, company)
+	elif has_serial_no:
 		locations = get_available_item_locations_for_serialized_item(item_code, from_warehouses, required_qty, company)
-	elif frappe.get_cached_value('Item', item_code, 'has_batch_no'):
+	elif has_batch_no:
 		locations = get_available_item_locations_for_batched_item(item_code, from_warehouses, required_qty, company)
 	else:
 		locations = get_available_item_locations_for_other_item(item_code, from_warehouses, required_qty, company)
@@ -158,8 +177,9 @@
 	remaining_qty = required_qty - total_qty_available
 
 	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)))
+		frappe.msgprint(_('{0} units of Item {1} is not available.')
+			.format(remaining_qty, frappe.get_desk_link('Item', item_code)),
+			title=_("Insufficient Stock"))
 
 	return locations
 
@@ -226,6 +246,34 @@
 
 	return batch_locations
 
+def get_available_item_locations_for_serial_and_batched_item(item_code, from_warehouses, required_qty, company):
+	# Get batch nos by FIFO
+	locations = get_available_item_locations_for_batched_item(item_code, from_warehouses, required_qty, company)
+
+	filters = frappe._dict({
+		'item_code': item_code,
+		'company': company,
+		'warehouse': ['!=', ''],
+		'batch_no': ''
+	})
+
+	# Get Serial Nos by FIFO for Batch No
+	for location in locations:
+		filters.batch_no = location.batch_no
+		filters.warehouse = location.warehouse
+		location.qty = required_qty if location.qty > required_qty else location.qty # if extra qty in batch
+
+		serial_nos = frappe.get_list('Serial No',
+			fields=['name'],
+			filters=filters,
+			limit=location.qty,
+			order_by='purchase_date')
+
+		serial_nos = [sn.name for sn in serial_nos]
+		location.serial_no = serial_nos
+
+	return locations
+
 def get_available_item_locations_for_other_item(item_code, from_warehouses, required_qty, company):
 	# gets all items available in different warehouses
 	warehouses = [x.get('name') for x in frappe.get_list("Warehouse", {'company': company}, "name")]
diff --git a/erpnext/stock/doctype/pick_list/test_pick_list.py b/erpnext/stock/doctype/pick_list/test_pick_list.py
index 1b9ff41..8ea7f89d 100644
--- a/erpnext/stock/doctype/pick_list/test_pick_list.py
+++ b/erpnext/stock/doctype/pick_list/test_pick_list.py
@@ -7,6 +7,8 @@
 import unittest
 test_dependencies = ['Item', 'Sales Invoice', 'Stock Entry', 'Batch']
 
+from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_purchase_receipt
+from erpnext.stock.doctype.item.test_item import create_item
 from erpnext.stock.doctype.stock_reconciliation.stock_reconciliation \
 		import EmptyStockReconciliationItemsError
 
@@ -49,7 +51,7 @@
 		self.assertEqual(pick_list.locations[0].warehouse, '_Test Warehouse - _TC')
 		self.assertEqual(pick_list.locations[0].qty, 5)
 
-	def test_pick_list_splits_row_according_to_warhouse_availability(self):
+	def test_pick_list_splits_row_according_to_warehouse_availability(self):
 		try:
 			frappe.get_doc({
 				'doctype': 'Stock Reconciliation',
@@ -122,7 +124,10 @@
 			}]
 		})
 
-		stock_reconciliation.submit()
+		try:
+			stock_reconciliation.submit()
+		except EmptyStockReconciliationItemsError:
+			pass
 
 		pick_list = frappe.get_doc({
 			'doctype': 'Pick List',
@@ -145,6 +150,85 @@
 		self.assertEqual(pick_list.locations[0].qty, 5)
 		self.assertEqual(pick_list.locations[0].serial_no, '123450\n123451\n123452\n123453\n123454')
 
+	def test_pick_list_shows_batch_no_for_batched_item(self):
+		# check if oldest batch no is picked
+		item = frappe.db.exists("Item", {'item_name': 'Batched Item'})
+		if not item:
+			item = create_item("Batched Item")
+			item.has_batch_no = 1
+			item.create_new_batch = 1
+			item.batch_number_series = "B-BATCH-.##"
+			item.save()
+		else:
+			item = frappe.get_doc("Item", {'item_name': 'Batched Item'})
+
+		pr1 = make_purchase_receipt(item_code="Batched Item", qty=1, rate=100.0)
+
+		pr1.load_from_db()
+		oldest_batch_no = pr1.items[0].batch_no
+
+		pr2 = make_purchase_receipt(item_code="Batched Item", qty=2, rate=100.0)
+
+		pick_list = frappe.get_doc({
+			'doctype': 'Pick List',
+			'company': '_Test Company',
+			'purpose': 'Material Transfer',
+			'locations': [{
+				'item_code': 'Batched Item',
+				'qty': 1,
+				'stock_qty': 1,
+				'conversion_factor': 1,
+			}]
+		})
+		pick_list.set_item_locations()
+
+		self.assertEqual(pick_list.locations[0].batch_no, oldest_batch_no)
+
+		pr1.cancel()
+		pr2.cancel()
+
+
+	def test_pick_list_for_batched_and_serialised_item(self):
+		# check if oldest batch no and serial nos are picked
+		item = frappe.db.exists("Item", {'item_name': 'Batched and Serialised Item'})
+		if not item:
+			item = create_item("Batched and Serialised Item")
+			item.has_batch_no = 1
+			item.create_new_batch = 1
+			item.has_serial_no = 1
+			item.batch_number_series = "B-BATCH-.##"
+			item.serial_no_series = "S-.####"
+			item.save()
+		else:
+			item = frappe.get_doc("Item", {'item_name': 'Batched and Serialised Item'})
+
+		pr1 = make_purchase_receipt(item_code="Batched and Serialised Item", qty=2, rate=100.0)
+
+		pr1.load_from_db()
+		oldest_batch_no = pr1.items[0].batch_no
+		oldest_serial_nos = pr1.items[0].serial_no
+
+		pr2 = make_purchase_receipt(item_code="Batched and Serialised Item", qty=2, rate=100.0)
+
+		pick_list = frappe.get_doc({
+			'doctype': 'Pick List',
+			'company': '_Test Company',
+			'purpose': 'Material Transfer',
+			'locations': [{
+				'item_code': 'Batched and Serialised Item',
+				'qty': 2,
+				'stock_qty': 2,
+				'conversion_factor': 1,
+			}]
+		})
+		pick_list.set_item_locations()
+
+		self.assertEqual(pick_list.locations[0].batch_no, oldest_batch_no)
+		self.assertEqual(pick_list.locations[0].serial_no, oldest_serial_nos)
+
+		pr1.cancel()
+		pr2.cancel()
+
 	def test_pick_list_for_items_from_multiple_sales_orders(self):
 		try:
 			frappe.get_doc({
diff --git a/erpnext/stock/doctype/pick_list_item/pick_list_item.json b/erpnext/stock/doctype/pick_list_item/pick_list_item.json
index 71fbf9a..8665986 100644
--- a/erpnext/stock/doctype/pick_list_item/pick_list_item.json
+++ b/erpnext/stock/doctype/pick_list_item/pick_list_item.json
@@ -180,7 +180,7 @@
  ],
  "istable": 1,
  "links": [],
- "modified": "2020-03-13 19:08:21.995986",
+ "modified": "2020-06-24 17:18:57.357120",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Pick List Item",
diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json
index 44d5f69..92e33ca 100755
--- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json
+++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json
@@ -1,6 +1,7 @@
 {
  "actions": [],
  "allow_import": 1,
+ "allow_workflow": 1,
  "autoname": "naming_series:",
  "creation": "2013-05-21 16:16:39",
  "doctype": "DocType",
@@ -104,6 +105,7 @@
   "bill_no",
   "bill_date",
   "more_info",
+  "project",
   "status",
   "amended_from",
   "range",
@@ -132,17 +134,13 @@
   {
    "fieldname": "supplier_section",
    "fieldtype": "Section Break",
-   "options": "fa fa-user",
-   "show_days": 1,
-   "show_seconds": 1
+   "options": "fa fa-user"
   },
   {
    "fieldname": "column_break0",
    "fieldtype": "Column Break",
    "oldfieldtype": "Column Break",
    "print_width": "50%",
-   "show_days": 1,
-   "show_seconds": 1,
    "width": "50%"
   },
   {
@@ -153,9 +151,7 @@
    "hidden": 1,
    "label": "Title",
    "no_copy": 1,
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "fieldname": "naming_series",
@@ -167,9 +163,7 @@
    "options": "MAT-PRE-.YYYY.-",
    "print_hide": 1,
    "reqd": 1,
-   "set_only_once": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "set_only_once": 1
   },
   {
    "bold": 1,
@@ -184,8 +178,6 @@
    "print_width": "150px",
    "reqd": 1,
    "search_index": 1,
-   "show_days": 1,
-   "show_seconds": 1,
    "width": "150px"
   },
   {
@@ -196,24 +188,18 @@
    "fieldtype": "Data",
    "in_global_search": 1,
    "label": "Supplier Name",
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "supplier_delivery_note",
    "fieldtype": "Data",
-   "label": "Supplier Delivery Note",
-   "show_days": 1,
-   "show_seconds": 1
+   "label": "Supplier Delivery Note"
   },
   {
    "fieldname": "column_break1",
    "fieldtype": "Column Break",
    "oldfieldtype": "Column Break",
    "print_width": "50%",
-   "show_days": 1,
-   "show_seconds": 1,
    "width": "50%"
   },
   {
@@ -228,8 +214,6 @@
    "print_width": "100px",
    "reqd": 1,
    "search_index": 1,
-   "show_days": 1,
-   "show_seconds": 1,
    "width": "100px"
   },
   {
@@ -243,8 +227,6 @@
    "print_hide": 1,
    "print_width": "100px",
    "reqd": 1,
-   "show_days": 1,
-   "show_seconds": 1,
    "width": "100px"
   },
   {
@@ -253,9 +235,7 @@
    "fieldname": "set_posting_time",
    "fieldtype": "Check",
    "label": "Edit Posting Date and Time",
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "fieldname": "company",
@@ -269,8 +249,6 @@
    "print_width": "150px",
    "remember_last_selected_value": 1,
    "reqd": 1,
-   "show_days": 1,
-   "show_seconds": 1,
    "width": "150px"
   },
   {
@@ -280,9 +258,7 @@
    "label": "Is Return",
    "no_copy": 1,
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "depends_on": "is_return",
@@ -292,60 +268,46 @@
    "no_copy": 1,
    "options": "Purchase Receipt",
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "collapsible": 1,
    "fieldname": "section_addresses",
    "fieldtype": "Section Break",
-   "label": "Address and Contact",
-   "show_days": 1,
-   "show_seconds": 1
+   "label": "Address and Contact"
   },
   {
    "fieldname": "supplier_address",
    "fieldtype": "Link",
    "label": "Select Supplier Address",
    "options": "Address",
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "fieldname": "contact_person",
    "fieldtype": "Link",
    "label": "Contact Person",
    "options": "Contact",
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "fieldname": "address_display",
    "fieldtype": "Small Text",
    "label": "Address",
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "contact_display",
    "fieldtype": "Small Text",
    "in_global_search": 1,
    "label": "Contact",
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "contact_mobile",
    "fieldtype": "Small Text",
    "label": "Mobile No",
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "contact_email",
@@ -353,42 +315,32 @@
    "label": "Contact Email",
    "options": "Email",
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "col_break_address",
-   "fieldtype": "Column Break",
-   "show_days": 1,
-   "show_seconds": 1
+   "fieldtype": "Column Break"
   },
   {
    "fieldname": "shipping_address",
    "fieldtype": "Link",
    "label": "Select Shipping Address",
    "options": "Address",
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "fieldname": "shipping_address_display",
    "fieldtype": "Small Text",
    "label": "Shipping Address",
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "collapsible": 1,
    "fieldname": "currency_and_price_list",
    "fieldtype": "Section Break",
    "label": "Currency and Price List",
-   "options": "fa fa-tag",
-   "show_days": 1,
-   "show_seconds": 1
+   "options": "fa fa-tag"
   },
   {
    "fieldname": "currency",
@@ -398,9 +350,7 @@
    "oldfieldtype": "Select",
    "options": "Currency",
    "print_hide": 1,
-   "reqd": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "reqd": 1
   },
   {
    "description": "Rate at which supplier's currency is converted to company's base currency",
@@ -411,17 +361,13 @@
    "oldfieldtype": "Currency",
    "precision": "9",
    "print_hide": 1,
-   "reqd": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "reqd": 1
   },
   {
    "fieldname": "column_break2",
    "fieldtype": "Column Break",
    "oldfieldtype": "Column Break",
    "print_width": "50%",
-   "show_days": 1,
-   "show_seconds": 1,
    "width": "50%"
   },
   {
@@ -429,9 +375,7 @@
    "fieldtype": "Link",
    "label": "Price List",
    "options": "Price List",
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "depends_on": "buying_price_list",
@@ -440,9 +384,7 @@
    "label": "Price List Currency",
    "options": "Currency",
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "depends_on": "buying_price_list",
@@ -450,9 +392,7 @@
    "fieldtype": "Float",
    "label": "Price List Exchange Rate",
    "precision": "9",
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "default": "0",
@@ -461,15 +401,11 @@
    "label": "Ignore Pricing Rule",
    "no_copy": 1,
    "permlevel": 1,
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "fieldname": "sec_warehouse",
-   "fieldtype": "Section Break",
-   "show_days": 1,
-   "show_seconds": 1
+   "fieldtype": "Section Break"
   },
   {
    "description": "Sets 'Accepted Warehouse' in each row of the items table.",
@@ -477,9 +413,7 @@
    "fieldtype": "Link",
    "label": "Accepted Warehouse",
    "options": "Warehouse",
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "description": "Sets 'Rejected Warehouse' in each row of the items table.",
@@ -490,15 +424,11 @@
    "oldfieldname": "rejected_warehouse",
    "oldfieldtype": "Link",
    "options": "Warehouse",
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "fieldname": "col_break_warehouse",
-   "fieldtype": "Column Break",
-   "show_days": 1,
-   "show_seconds": 1
+   "fieldtype": "Column Break"
   },
   {
    "default": "No",
@@ -508,9 +438,7 @@
    "oldfieldname": "is_subcontracted",
    "oldfieldtype": "Select",
    "options": "No\nYes",
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "depends_on": "eval:doc.is_subcontracted==\"Yes\"",
@@ -523,17 +451,13 @@
    "options": "Warehouse",
    "print_hide": 1,
    "print_width": "50px",
-   "show_days": 1,
-   "show_seconds": 1,
    "width": "50px"
   },
   {
    "fieldname": "items_section",
    "fieldtype": "Section Break",
    "oldfieldtype": "Section Break",
-   "options": "fa fa-shopping-cart",
-   "show_days": 1,
-   "show_seconds": 1
+   "options": "fa fa-shopping-cart"
   },
   {
    "allow_bulk_edit": 1,
@@ -543,26 +467,20 @@
    "oldfieldname": "purchase_receipt_details",
    "oldfieldtype": "Table",
    "options": "Purchase Receipt Item",
-   "reqd": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "reqd": 1
   },
   {
    "collapsible": 1,
    "fieldname": "pricing_rule_details",
    "fieldtype": "Section Break",
-   "label": "Pricing Rules",
-   "show_days": 1,
-   "show_seconds": 1
+   "label": "Pricing Rules"
   },
   {
    "fieldname": "pricing_rules",
    "fieldtype": "Table",
    "label": "Pricing Rule Detail",
    "options": "Pricing Rule Detail",
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "depends_on": "supplied_items",
@@ -571,9 +489,7 @@
    "label": "Get Current Stock",
    "oldfieldtype": "Button",
    "options": "get_current_stock",
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "collapsible": 1,
@@ -584,9 +500,7 @@
    "oldfieldtype": "Section Break",
    "options": "fa fa-table",
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "supplied_items",
@@ -597,24 +511,18 @@
    "oldfieldtype": "Table",
    "options": "Purchase Receipt Item Supplied",
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "section_break0",
    "fieldtype": "Section Break",
-   "oldfieldtype": "Section Break",
-   "show_days": 1,
-   "show_seconds": 1
+   "oldfieldtype": "Section Break"
   },
   {
    "fieldname": "total_qty",
    "fieldtype": "Float",
    "label": "Total Quantity",
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "base_total",
@@ -622,9 +530,7 @@
    "label": "Total (Company Currency)",
    "options": "Company:company:default_currency",
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "base_net_total",
@@ -637,24 +543,18 @@
    "print_width": "150px",
    "read_only": 1,
    "reqd": 1,
-   "show_days": 1,
-   "show_seconds": 1,
    "width": "150px"
   },
   {
    "fieldname": "column_break_27",
-   "fieldtype": "Column Break",
-   "show_days": 1,
-   "show_seconds": 1
+   "fieldtype": "Column Break"
   },
   {
    "fieldname": "total",
    "fieldtype": "Currency",
    "label": "Total",
    "options": "currency",
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "net_total",
@@ -664,56 +564,42 @@
    "oldfieldtype": "Currency",
    "options": "currency",
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "total_net_weight",
    "fieldtype": "Float",
    "label": "Total Net Weight",
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "description": "Add / Edit Taxes and Charges",
    "fieldname": "taxes_charges_section",
    "fieldtype": "Section Break",
    "oldfieldtype": "Section Break",
-   "options": "fa fa-money",
-   "show_days": 1,
-   "show_seconds": 1
+   "options": "fa fa-money"
   },
   {
    "fieldname": "tax_category",
    "fieldtype": "Link",
    "label": "Tax Category",
    "options": "Tax Category",
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "fieldname": "shipping_col",
-   "fieldtype": "Column Break",
-   "show_days": 1,
-   "show_seconds": 1
+   "fieldtype": "Column Break"
   },
   {
    "fieldname": "shipping_rule",
    "fieldtype": "Link",
    "label": "Shipping Rule",
-   "options": "Shipping Rule",
-   "show_days": 1,
-   "show_seconds": 1
+   "options": "Shipping Rule"
   },
   {
    "fieldname": "taxes_section",
-   "fieldtype": "Section Break",
-   "show_days": 1,
-   "show_seconds": 1
+   "fieldtype": "Section Break"
   },
   {
    "fieldname": "taxes_and_charges",
@@ -722,9 +608,7 @@
    "oldfieldname": "purchase_other_charges",
    "oldfieldtype": "Link",
    "options": "Purchase Taxes and Charges Template",
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "fieldname": "taxes",
@@ -732,17 +616,13 @@
    "label": "Purchase Taxes and Charges",
    "oldfieldname": "purchase_tax_details",
    "oldfieldtype": "Table",
-   "options": "Purchase Taxes and Charges",
-   "show_days": 1,
-   "show_seconds": 1
+   "options": "Purchase Taxes and Charges"
   },
   {
    "collapsible": 1,
    "fieldname": "sec_tax_breakup",
    "fieldtype": "Section Break",
-   "label": "Tax Breakup",
-   "show_days": 1,
-   "show_seconds": 1
+   "label": "Tax Breakup"
   },
   {
    "fieldname": "other_charges_calculation",
@@ -751,17 +631,13 @@
    "no_copy": 1,
    "oldfieldtype": "HTML",
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "totals",
    "fieldtype": "Section Break",
    "oldfieldtype": "Section Break",
-   "options": "fa fa-money",
-   "show_days": 1,
-   "show_seconds": 1
+   "options": "fa fa-money"
   },
   {
    "fieldname": "base_taxes_and_charges_added",
@@ -771,9 +647,7 @@
    "oldfieldtype": "Currency",
    "options": "Company:company:default_currency",
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "base_taxes_and_charges_deducted",
@@ -783,9 +657,7 @@
    "oldfieldtype": "Currency",
    "options": "Company:company:default_currency",
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "base_total_taxes_and_charges",
@@ -795,16 +667,12 @@
    "oldfieldtype": "Currency",
    "options": "Company:company:default_currency",
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "column_break3",
    "fieldtype": "Column Break",
    "print_width": "50%",
-   "show_days": 1,
-   "show_seconds": 1,
    "width": "50%"
   },
   {
@@ -815,9 +683,7 @@
    "oldfieldtype": "Currency",
    "options": "currency",
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "taxes_and_charges_deducted",
@@ -827,9 +693,7 @@
    "oldfieldtype": "Currency",
    "options": "currency",
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "total_taxes_and_charges",
@@ -837,18 +701,14 @@
    "label": "Total Taxes and Charges",
    "options": "currency",
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "collapsible": 1,
    "collapsible_depends_on": "discount_amount",
    "fieldname": "section_break_42",
    "fieldtype": "Section Break",
-   "label": "Additional Discount",
-   "show_days": 1,
-   "show_seconds": 1
+   "label": "Additional Discount"
   },
   {
    "default": "Grand Total",
@@ -856,9 +716,7 @@
    "fieldtype": "Select",
    "label": "Apply Additional Discount On",
    "options": "\nGrand Total\nNet Total",
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "fieldname": "base_discount_amount",
@@ -866,38 +724,28 @@
    "label": "Additional Discount Amount (Company Currency)",
    "options": "Company:company:default_currency",
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "column_break_44",
-   "fieldtype": "Column Break",
-   "show_days": 1,
-   "show_seconds": 1
+   "fieldtype": "Column Break"
   },
   {
    "fieldname": "additional_discount_percentage",
    "fieldtype": "Float",
    "label": "Additional Discount Percentage",
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "fieldname": "discount_amount",
    "fieldtype": "Currency",
    "label": "Additional Discount Amount",
    "options": "currency",
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "fieldname": "section_break_46",
-   "fieldtype": "Section Break",
-   "show_days": 1,
-   "show_seconds": 1
+   "fieldtype": "Section Break"
   },
   {
    "fieldname": "base_grand_total",
@@ -907,9 +755,7 @@
    "oldfieldtype": "Currency",
    "options": "Company:company:default_currency",
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "base_rounding_adjustment",
@@ -918,20 +764,17 @@
    "no_copy": 1,
    "options": "Company:company:default_currency",
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "base_in_words",
    "fieldtype": "Data",
    "label": "In Words (Company Currency)",
+   "length": 240,
    "oldfieldname": "in_words",
    "oldfieldtype": "Data",
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "base_rounded_total",
@@ -941,15 +784,11 @@
    "oldfieldtype": "Currency",
    "options": "Company:company:default_currency",
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "column_break_50",
-   "fieldtype": "Column Break",
-   "show_days": 1,
-   "show_seconds": 1
+   "fieldtype": "Column Break"
   },
   {
    "fieldname": "grand_total",
@@ -959,9 +798,7 @@
    "oldfieldname": "grand_total_import",
    "oldfieldtype": "Currency",
    "options": "currency",
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "rounding_adjustment",
@@ -970,9 +807,7 @@
    "no_copy": 1,
    "options": "currency",
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "depends_on": "eval:!doc.disable_rounded_total",
@@ -982,28 +817,23 @@
    "no_copy": 1,
    "options": "currency",
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "in_words",
    "fieldtype": "Data",
    "label": "In Words",
+   "length": 240,
    "oldfieldname": "in_words_import",
    "oldfieldtype": "Data",
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "default": "0",
    "fieldname": "disable_rounded_total",
    "fieldtype": "Check",
-   "label": "Disable Rounded Total",
-   "show_days": 1,
-   "show_seconds": 1
+   "label": "Disable Rounded Total"
   },
   {
    "collapsible": 1,
@@ -1012,9 +842,7 @@
    "fieldtype": "Section Break",
    "label": "Terms and Conditions",
    "oldfieldtype": "Section Break",
-   "options": "fa fa-legal",
-   "show_days": 1,
-   "show_seconds": 1
+   "options": "fa fa-legal"
   },
   {
    "fieldname": "tc_name",
@@ -1023,18 +851,14 @@
    "oldfieldname": "tc_name",
    "oldfieldtype": "Link",
    "options": "Terms and Conditions",
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "fieldname": "terms",
    "fieldtype": "Text Editor",
    "label": "Terms and Conditions",
    "oldfieldname": "terms",
-   "oldfieldtype": "Text Editor",
-   "show_days": 1,
-   "show_seconds": 1
+   "oldfieldtype": "Text Editor"
   },
   {
    "fieldname": "bill_no",
@@ -1043,9 +867,7 @@
    "label": "Bill No",
    "oldfieldname": "bill_no",
    "oldfieldtype": "Data",
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "fieldname": "bill_date",
@@ -1054,9 +876,7 @@
    "label": "Bill Date",
    "oldfieldname": "bill_date",
    "oldfieldtype": "Date",
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "collapsible": 1,
@@ -1064,9 +884,7 @@
    "fieldtype": "Section Break",
    "label": "More Information",
    "oldfieldtype": "Section Break",
-   "options": "fa fa-file-text",
-   "show_days": 1,
-   "show_seconds": 1
+   "options": "fa fa-file-text"
   },
   {
    "default": "Draft",
@@ -1083,8 +901,6 @@
    "read_only": 1,
    "reqd": 1,
    "search_index": 1,
-   "show_days": 1,
-   "show_seconds": 1,
    "width": "150px"
   },
   {
@@ -1100,8 +916,6 @@
    "print_hide": 1,
    "print_width": "150px",
    "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1,
    "width": "150px"
   },
   {
@@ -1111,9 +925,7 @@
    "label": "Range",
    "oldfieldname": "range",
    "oldfieldtype": "Data",
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "fieldname": "column_break4",
@@ -1121,26 +933,27 @@
    "oldfieldtype": "Column Break",
    "print_hide": 1,
    "print_width": "50%",
-   "show_days": 1,
-   "show_seconds": 1,
    "width": "50%"
   },
   {
+   "description": "Track this Purchase Receipt against any Project",
+   "fieldname": "project",
+   "fieldtype": "Link",
+   "label": "Project",
+   "options": "Project"
+  },
+  {
    "fieldname": "per_billed",
    "fieldtype": "Percent",
    "label": "% Amount Billed",
    "no_copy": 1,
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "subscription_detail",
    "fieldtype": "Section Break",
-   "label": "Auto Repeat Detail",
-   "show_days": 1,
-   "show_seconds": 1
+   "label": "Auto Repeat Detail"
   },
   {
    "fieldname": "auto_repeat",
@@ -1149,17 +962,13 @@
    "no_copy": 1,
    "options": "Auto Repeat",
    "print_hide": 1,
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "collapsible": 1,
    "fieldname": "printing_settings",
    "fieldtype": "Section Break",
-   "label": "Printing Settings",
-   "show_days": 1,
-   "show_seconds": 1
+   "label": "Printing Settings"
   },
   {
    "allow_on_submit": 1,
@@ -1167,9 +976,7 @@
    "fieldtype": "Link",
    "label": "Letter Head",
    "options": "Letter Head",
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "allow_on_submit": 1,
@@ -1181,17 +988,13 @@
    "oldfieldtype": "Link",
    "options": "Print Heading",
    "print_hide": 1,
-   "report_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "report_hide": 1
   },
   {
    "fieldname": "language",
    "fieldtype": "Data",
    "label": "Print Language",
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "allow_on_submit": 1,
@@ -1199,15 +1002,11 @@
    "fieldname": "group_same_items",
    "fieldtype": "Check",
    "label": "Group same items",
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "fieldname": "column_break_97",
-   "fieldtype": "Column Break",
-   "show_days": 1,
-   "show_seconds": 1
+   "fieldtype": "Column Break"
   },
   {
    "fieldname": "other_details",
@@ -1218,8 +1017,6 @@
    "options": "<div class=\"columnHeading\">Other Details</div>",
    "print_hide": 1,
    "print_width": "30%",
-   "show_days": 1,
-   "show_seconds": 1,
    "width": "30%"
   },
   {
@@ -1227,17 +1024,13 @@
    "fieldtype": "Small Text",
    "label": "Instructions",
    "oldfieldname": "instructions",
-   "oldfieldtype": "Text",
-   "show_days": 1,
-   "show_seconds": 1
+   "oldfieldtype": "Text"
   },
   {
    "fieldname": "remarks",
    "fieldtype": "Small Text",
    "label": "Remarks",
-   "print_hide": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "print_hide": 1
   },
   {
    "collapsible": 1,
@@ -1245,25 +1038,19 @@
    "fieldname": "transporter_info",
    "fieldtype": "Section Break",
    "label": "Transporter Details",
-   "options": "fa fa-truck",
-   "show_days": 1,
-   "show_seconds": 1
+   "options": "fa fa-truck"
   },
   {
    "fieldname": "transporter_name",
    "fieldtype": "Data",
    "label": "Transporter Name",
    "oldfieldname": "transporter_name",
-   "oldfieldtype": "Data",
-   "show_days": 1,
-   "show_seconds": 1
+   "oldfieldtype": "Data"
   },
   {
    "fieldname": "column_break5",
    "fieldtype": "Column Break",
    "print_width": "50%",
-   "show_days": 1,
-   "show_seconds": 1,
    "width": "50%"
   },
   {
@@ -1274,8 +1061,6 @@
    "oldfieldname": "lr_no",
    "oldfieldtype": "Data",
    "print_width": "100px",
-   "show_days": 1,
-   "show_seconds": 1,
    "width": "100px"
   },
   {
@@ -1286,8 +1071,6 @@
    "oldfieldname": "lr_date",
    "oldfieldtype": "Date",
    "print_width": "100px",
-   "show_days": 1,
-   "show_seconds": 1,
    "width": "100px"
   },
   {
@@ -1296,48 +1079,38 @@
    "fieldname": "is_internal_supplier",
    "fieldtype": "Check",
    "label": "Is Internal Supplier",
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "inter_company_reference",
    "fieldtype": "Link",
    "label": "Inter Company Reference",
    "options": "Delivery Note",
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   },
   {
    "fieldname": "scan_barcode",
    "fieldtype": "Data",
-   "label": "Scan Barcode",
-   "show_days": 1,
-   "show_seconds": 1
+   "label": "Scan Barcode"
   },
   {
    "fieldname": "billing_address",
    "fieldtype": "Link",
    "label": "Select Billing Address",
-   "options": "Address",
-   "show_days": 1,
-   "show_seconds": 1
+   "options": "Address"
   },
   {
    "fieldname": "billing_address_display",
    "fieldtype": "Small Text",
    "label": "Billing Address",
-   "read_only": 1,
-   "show_days": 1,
-   "show_seconds": 1
+   "read_only": 1
   }
  ],
  "icon": "fa fa-truck",
  "idx": 261,
  "is_submittable": 1,
  "links": [],
- "modified": "2020-06-13 22:26:03.600092",
+ "modified": "2020-07-18 05:19:12.148115",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Purchase Receipt",
diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
index e6ab8d6..d0ba001 100644
--- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
+++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
@@ -211,6 +211,7 @@
 		stock_rbnb = self.get_company_default("stock_received_but_not_billed")
 		landed_cost_entries = get_item_account_wise_additional_cost(self.name)
 		expenses_included_in_valuation = self.get_company_default("expenses_included_in_valuation")
+		auto_accounting_for_non_stock_items = cint(frappe.db.get_value('Company', self.company, 'enable_perpetual_inventory_for_non_stock_items'))
 
 		gl_entries = []
 		warehouse_with_no_account = []
@@ -301,6 +302,32 @@
 				elif d.warehouse not in warehouse_with_no_account or \
 					d.rejected_warehouse not in warehouse_with_no_account:
 						warehouse_with_no_account.append(d.warehouse)
+			elif d.item_code not in stock_items and flt(d.qty) and auto_accounting_for_non_stock_items:
+
+				service_received_but_not_billed_account = self.get_company_default("service_received_but_not_billed")
+				credit_currency = get_account_currency(service_received_but_not_billed_account)
+
+				gl_entries.append(self.get_gl_dict({
+					"account": service_received_but_not_billed_account,
+					"against": d.expense_account,
+					"cost_center": d.cost_center,
+					"remarks": self.get("remarks") or _("Accounting Entry for Service"),
+					"project": d.project,
+					"credit": d.amount,
+					"voucher_detail_no": d.name
+				}, credit_currency, item=d))
+
+				debit_currency = get_account_currency(d.expense_account)
+
+				gl_entries.append(self.get_gl_dict({
+					"account": d.expense_account,
+					"against": service_received_but_not_billed_account,
+					"cost_center": d.cost_center,
+					"remarks": self.get("remarks") or _("Accounting Entry for Service"),
+					"project": d.project,
+					"debit": d.amount,
+					"voucher_detail_no": d.name
+				}, debit_currency, item=d))
 
 		self.get_asset_gl_entry(gl_entries)
 		# Cost center-wise amount breakup for other charges included for valuation
diff --git a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py
index 649cfdc..d97b9e8 100644
--- a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py
+++ b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py
@@ -403,11 +403,8 @@
 
 		pr_return.submit()
 
-	def test_purchase_receipt_for_enable_allow_cost_center_in_entry_of_bs_account(self):
+	def test_purchase_receipt_cost_center(self):
 		from erpnext.accounts.doctype.cost_center.test_cost_center import create_cost_center
-		accounts_settings = frappe.get_doc('Accounts Settings', 'Accounts Settings')
-		accounts_settings.allow_cost_center_in_entry_of_bs_account = 1
-		accounts_settings.save()
 		cost_center = "_Test Cost Center for BS Account - TCP1"
 		create_cost_center(cost_center_name="_Test Cost Center for BS Account", company="_Test Company with perpetual inventory")
 
@@ -435,14 +432,7 @@
 		for i, gle in enumerate(gl_entries):
 			self.assertEqual(expected_values[gle.account]["cost_center"], gle.cost_center)
 
-		accounts_settings.allow_cost_center_in_entry_of_bs_account = 0
-		accounts_settings.save()
-
-	def test_purchase_receipt_for_disable_allow_cost_center_in_entry_of_bs_account(self):
-		accounts_settings = frappe.get_doc('Accounts Settings', 'Accounts Settings')
-		accounts_settings.allow_cost_center_in_entry_of_bs_account = 0
-		accounts_settings.save()
-
+	def test_purchase_receipt_cost_center_with_balance_sheet_account(self):
 		if not frappe.db.exists('Location', 'Test Location'):
 			frappe.get_doc({
 				'doctype': 'Location',
@@ -454,13 +444,14 @@
 		gl_entries = get_gl_entries("Purchase Receipt", pr.name)
 
 		self.assertTrue(gl_entries)
+		cost_center = pr.get('items')[0].cost_center
 
 		expected_values = {
 			"Stock Received But Not Billed - TCP1": {
-				"cost_center": None
+				"cost_center": cost_center
 			},
 			stock_in_hand_account: {
-				"cost_center": None
+				"cost_center": cost_center
 			}
 		}
 		for i, gle in enumerate(gl_entries):
diff --git a/erpnext/stock/doctype/quality_inspection/quality_inspection.py b/erpnext/stock/doctype/quality_inspection/quality_inspection.py
index 37ab807..568e742 100644
--- a/erpnext/stock/doctype/quality_inspection/quality_inspection.py
+++ b/erpnext/stock/doctype/quality_inspection/quality_inspection.py
@@ -58,6 +58,7 @@
 				.format(parent_doc=self.reference_type, child_doc=doctype),
 				(quality_inspection, self.modified, self.reference_name, self.item_code))
 
+@frappe.whitelist()
 def item_query(doctype, txt, searchfield, start, page_len, filters):
 	if filters.get("from"):
 		from frappe.desk.reportview import get_match_cond
@@ -86,6 +87,7 @@
 			page_len = page_len, qi_condition = qi_condition),
 			{'parent': filters.get('parent'), 'txt': "%%%s%%" % txt})
 
+@frappe.whitelist()
 def quality_inspection_query(doctype, txt, searchfield, start, page_len, filters):
 	return frappe.get_all('Quality Inspection',
 		limit_start=start,
@@ -118,4 +120,4 @@
 		}
 	}, target_doc, postprocess)
 
-	return doc
\ No newline at end of file
+	return doc
diff --git a/erpnext/stock/doctype/serial_no/serial_no.json b/erpnext/stock/doctype/serial_no/serial_no.json
index d9f8b62..3acf3a9 100644
--- a/erpnext/stock/doctype/serial_no/serial_no.json
+++ b/erpnext/stock/doctype/serial_no/serial_no.json
@@ -427,7 +427,7 @@
  "icon": "fa fa-barcode",
  "idx": 1,
  "links": [],
- "modified": "2020-05-21 19:29:58.517772",
+ "modified": "2020-07-20 20:50:16.660433",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Serial No",
diff --git a/erpnext/stock/doctype/serial_no/serial_no.py b/erpnext/stock/doctype/serial_no/serial_no.py
index f3514c7..f7ff916 100644
--- a/erpnext/stock/doctype/serial_no/serial_no.py
+++ b/erpnext/stock/doctype/serial_no/serial_no.py
@@ -3,6 +3,7 @@
 
 from __future__ import unicode_literals
 import frappe
+import json
 
 from frappe.model.naming import make_autoname
 from frappe.utils import cint, cstr, flt, add_days, nowdate, getdate
@@ -197,7 +198,7 @@
 	def after_rename(self, old, new, merge=False):
 		"""rename serial_no text fields"""
 		for dt in frappe.db.sql("""select parent from tabDocField
-			where fieldname='serial_no' and fieldtype in ('Text', 'Small Text')"""):
+			where fieldname='serial_no' and fieldtype in ('Text', 'Small Text', 'Long Text')"""):
 
 			for item in frappe.db.sql("""select name, serial_no from `tab%s`
 				where serial_no like %s""" % (dt[0], frappe.db.escape('%' + old + '%'))):
@@ -537,15 +538,54 @@
 	return serial_nos
 
 @frappe.whitelist()
-def auto_fetch_serial_number(qty, item_code, warehouse, batch_nos=None):
-	import json
+def auto_fetch_serial_number(qty, item_code, warehouse, batch_nos=None, for_doctype=None):
 	filters = {
 		"item_code": item_code,
 		"warehouse": warehouse,
 		"delivery_document_no": "",
 		"sales_invoice": ""
 	}
-	if batch_nos: filters["batch_no"] = ["in", json.loads(batch_nos)]
+
+	if batch_nos:
+		try:
+			filters["batch_no"] = ["in", json.loads(batch_nos)]
+		except:
+			filters["batch_no"] = ["in", [batch_nos]]
+
+	if for_doctype == 'POS Invoice':
+		reserved_serial_nos, unreserved_serial_nos = get_pos_reserved_serial_nos(filters, qty)
+		return unreserved_serial_nos
 
 	serial_numbers = frappe.get_list("Serial No", filters=filters, limit=qty, order_by="creation")
 	return [item['name'] for item in serial_numbers]
+
+@frappe.whitelist()
+def get_pos_reserved_serial_nos(filters, qty=None):
+	batch_no_cond = ""
+	if filters.get("batch_no"):
+		batch_no_cond = "and item.batch_no = {}".format(frappe.db.escape(filters.get('batch_no')))
+
+	reserved_serial_nos_str = [d.serial_no for d in frappe.db.sql("""select item.serial_no as serial_no
+		from `tabPOS Invoice` p, `tabPOS Invoice Item` item
+		where p.name = item.parent 
+		and p.consolidated_invoice is NULL 
+		and p.docstatus = 1
+		and item.docstatus = 1
+		and item.item_code = %s
+		and item.warehouse = %s
+		{}
+		""".format(batch_no_cond), [filters.get('item_code'), filters.get('warehouse')], as_dict=1)]
+
+	reserved_serial_nos = []
+	for s in reserved_serial_nos_str:
+		if not s: continue
+
+		serial_nos = s.split("\n")
+		serial_nos = ' '.join(serial_nos).split() # remove whitespaces
+		if len(serial_nos): reserved_serial_nos += serial_nos
+
+	filters["name"] = ["not in", reserved_serial_nos]
+	serial_numbers = frappe.get_list("Serial No", filters=filters, limit=qty, order_by="creation")
+	unreserved_serial_nos = [item['name'] for item in serial_numbers]
+
+	return reserved_serial_nos, unreserved_serial_nos
\ No newline at end of file
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py
index 5fbd512..229cf02 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.py
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.py
@@ -574,9 +574,7 @@
 						{"parent": self.purchase_order, "item_code": se_item.subcontracted_item},
 						"bom")
 
-					allow_alternative_item = frappe.get_value("BOM", bom_no, "allow_alternative_item")
-
-					if allow_alternative_item:
+					if se_item.allow_alternative_item:
 						original_item_code = frappe.get_value("Item Alternative", {"alternative_item_code": item_code}, "item_code")
 
 						required_qty = sum([flt(d.required_qty) for d in purchase_order.supplied_items \
@@ -743,7 +741,7 @@
 
 	def get_item_details(self, args=None, for_update=False):
 		item = frappe.db.sql("""select i.name, i.stock_uom, i.description, i.image, i.item_name, i.item_group,
-				i.has_batch_no, i.sample_quantity, i.has_serial_no,
+				i.has_batch_no, i.sample_quantity, i.has_serial_no, i.allow_alternative_item,
 				id.expense_account, id.buying_cost_center
 			from `tabItem` i LEFT JOIN `tabItem Default` id ON i.name=id.parent and id.company=%s
 			where i.name=%s
@@ -778,6 +776,9 @@
 			'expense_account'		: item.expense_account
 		})
 
+		if self.purpose == 'Send to Subcontractor':
+			ret["allow_alternative_item"] = item.allow_alternative_item
+
 		# update uom
 		if args.get("uom") and for_update:
 			ret.update(get_uom_details(args.get('item_code'), args.get('uom'), args.get('qty')))
diff --git a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.js b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.js
index dd284e4..ecee97c 100644
--- a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.js
+++ b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.js
@@ -74,6 +74,20 @@
 		, __("Get Items"), __("Update"));
 	},
 
+	posting_date: function(frm) {
+		frm.trigger("set_valuation_rate_and_qty_for_all_items");
+	},
+
+	posting_time: function(frm) {
+		frm.trigger("set_valuation_rate_and_qty_for_all_items");
+	},
+
+	set_valuation_rate_and_qty_for_all_items: function(frm) {
+		frm.doc.items.forEach(row => {
+			frm.events.set_valuation_rate_and_qty(frm, row.doctype, row.name);
+		});
+	},
+
 	set_valuation_rate_and_qty: function(frm, cdt, cdn) {
 		var d = frappe.model.get_doc(cdt, cdn);
 
diff --git a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py
index 5e469c2..43fbc00 100644
--- a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py
+++ b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py
@@ -184,8 +184,12 @@
 
 		sl_entries = []
 		has_serial_no = False
+		has_batch_no = False
 		for row in self.items:
 			item = frappe.get_doc("Item", row.item_code)
+			if item.has_batch_no:
+				has_batch_no = True
+
 			if item.has_serial_no or item.has_batch_no:
 				has_serial_no = True
 				self.get_sle_for_serialized_items(row, sl_entries)
@@ -222,7 +226,11 @@
 			if has_serial_no:
 				sl_entries = self.merge_similar_item_serial_nos(sl_entries)
 
-			self.make_sl_entries(sl_entries)
+			allow_negative_stock = False
+			if has_batch_no:
+				allow_negative_stock = True
+
+			self.make_sl_entries(sl_entries, allow_negative_stock=allow_negative_stock)
 
 		if has_serial_no and sl_entries:
 			self.update_valuation_rate_for_serial_no()
@@ -493,7 +501,7 @@
 		qty, rate = data
 
 	if item_dict.get("has_batch_no"):
-		qty = get_batch_qty(batch_no, warehouse) or 0
+		qty = get_batch_qty(batch_no, warehouse, posting_date=posting_date, posting_time=posting_time) or 0
 
 	return {
 		'qty': qty,
diff --git a/erpnext/stock/doctype/stock_settings/stock_settings.js b/erpnext/stock/doctype/stock_settings/stock_settings.js
index d5049ac..48624e0 100644
--- a/erpnext/stock/doctype/stock_settings/stock_settings.js
+++ b/erpnext/stock/doctype/stock_settings/stock_settings.js
@@ -20,7 +20,7 @@
 	{
 		fieldname: "item_naming_by",
 		title: __("Item Naming By"),
-		description: __("By default, the Item Name is set as per the Item Code entered. If you want Items to be named by a") + "<a href='https://docs.erpnext.com/docs/user/manual/en/setting-up/settings/naming-series' target='_blank'>Naming Series</a>" + __(" choose the 'Naming Series' option."),
+		description: __("By default, the Item Name is set as per the Item Code entered. If you want Items to be named by a ") + "<a href='https://docs.erpnext.com/docs/user/manual/en/setting-up/settings/naming-series' target='_blank'>Naming Series</a>" + __(" choose the 'Naming Series' option."),
 	},
 	{
 		fieldname: "default_warehouse",
diff --git a/erpnext/stock/doctype/stock_settings/stock_settings.json b/erpnext/stock/doctype/stock_settings/stock_settings.json
index c9a3527..9c5d3d8 100644
--- a/erpnext/stock/doctype/stock_settings/stock_settings.json
+++ b/erpnext/stock/doctype/stock_settings/stock_settings.json
@@ -216,7 +216,7 @@
  "idx": 1,
  "issingle": 1,
  "links": [],
- "modified": "2020-04-01 18:11:25.417678",
+ "modified": "2020-06-20 11:39:15.344112",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Stock Settings",
diff --git a/erpnext/stock/doctype/warehouse/warehouse.json b/erpnext/stock/doctype/warehouse/warehouse.json
index 5d534af..3b49c4c 100644
--- a/erpnext/stock/doctype/warehouse/warehouse.json
+++ b/erpnext/stock/doctype/warehouse/warehouse.json
@@ -10,12 +10,14 @@
  "field_order": [
   "warehouse_detail",
   "warehouse_name",
+  "column_break_3",
+  "warehouse_type",
+  "parent_warehouse",
   "is_group",
-  "company",
-  "disabled",
   "column_break_4",
   "account",
-  "warehouse_type",
+  "company",
+  "disabled",
   "address_and_contact",
   "address_html",
   "column_break_10",
@@ -31,7 +33,6 @@
   "state",
   "pin",
   "tree_details",
-  "parent_warehouse",
   "lft",
   "rgt",
   "old_parent"
@@ -91,6 +92,7 @@
    "options": "Account"
   },
   {
+   "depends_on": "eval:!doc.__islocal",
    "fieldname": "address_and_contact",
    "fieldtype": "Section Break",
    "label": "Address and Contact"
@@ -224,13 +226,17 @@
    "fieldtype": "Link",
    "label": "Warehouse Type",
    "options": "Warehouse Type"
+  },
+  {
+   "fieldname": "column_break_3",
+   "fieldtype": "Section Break"
   }
  ],
  "icon": "fa fa-building",
  "idx": 1,
  "is_tree": 1,
  "links": [],
- "modified": "2020-03-18 18:11:53.282358",
+ "modified": "2020-07-16 15:43:50.653256",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Warehouse",
diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py
index 0ed3b27..1a7c15e 100644
--- a/erpnext/stock/get_item_details.py
+++ b/erpnext/stock/get_item_details.py
@@ -47,6 +47,8 @@
 	"""
 
 	args = process_args(args)
+	for_validate = process_string_args(for_validate)
+	overwrite_warehouse = process_string_args(overwrite_warehouse)
 	item = frappe.get_cached_doc("Item", args.item_code)
 	validate_item_details(args, item)
 
@@ -166,6 +168,10 @@
 	set_transaction_type(args)
 	return args
 
+def process_string_args(args):
+	if isinstance(args, string_types):
+		args = json.loads(args)
+	return args
 
 @frappe.whitelist()
 def get_item_code(barcode=None, serial_no=None):
@@ -395,13 +401,30 @@
 	return warehouse
 
 def update_barcode_value(out):
-	from erpnext.accounts.doctype.sales_invoice.pos import get_barcode_data
 	barcode_data = get_barcode_data([out])
 
 	# If item has one barcode then update the value of the barcode field
 	if barcode_data and len(barcode_data.get(out.item_code)) == 1:
 		out['barcode'] = barcode_data.get(out.item_code)[0]
 
+def get_barcode_data(items_list):
+	# get itemwise batch no data
+	# exmaple: {'LED-GRE': [Batch001, Batch002]}
+	# where LED-GRE is item code, SN0001 is serial no and Pune is warehouse
+
+	itemwise_barcode = {}
+	for item in items_list:
+		barcodes = frappe.db.sql("""
+			select barcode from `tabItem Barcode` where parent = %s
+		""", item.item_code, as_dict=1)
+
+		for barcode in barcodes:
+			if item.item_code not in itemwise_barcode:
+				itemwise_barcode.setdefault(item.item_code, [])
+			itemwise_barcode[item.item_code].append(barcode.get("barcode"))
+
+	return itemwise_barcode
+
 @frappe.whitelist()
 def get_item_tax_info(company, tax_category, item_codes):
 	out = {}
@@ -413,7 +436,7 @@
 			continue
 		out[item_code] = {}
 		item = frappe.get_cached_doc("Item", item_code)
-		get_item_tax_template({"tax_category": tax_category}, item, out[item_code])
+		get_item_tax_template({"company": company, "tax_category": tax_category}, item, out[item_code])
 		out[item_code]["item_tax_rate"] = get_item_tax_map(company, out[item_code].get("item_tax_template"), as_json=True)
 
 	return out
@@ -442,7 +465,8 @@
 	taxes_with_no_validity = []
 
 	for tax in taxes:
-		if tax.valid_from:
+		tax_company = frappe.get_value("Item Tax Template", tax.item_tax_template, 'company')
+		if tax.valid_from and tax_company == args['company']:
 			# In purchase Invoice first preference will be given to supplier invoice date
 			# if supplier date is not present then posting date
 			validation_date = args.get('transaction_date') or args.get('bill_date') or args.get('posting_date')
@@ -450,7 +474,8 @@
 			if getdate(tax.valid_from) <= getdate(validation_date):
 				taxes_with_validity.append(tax)
 		else:
-			taxes_with_no_validity.append(tax)
+			if tax_company == args['company']:
+				taxes_with_no_validity.append(tax)
 
 	if taxes_with_validity:
 		taxes = sorted(taxes_with_validity, key = lambda i: i.valid_from, reverse=True)
@@ -637,6 +662,10 @@
 		conditions += """ and %(transaction_date)s between
 			ifnull(valid_from, '2000-01-01') and ifnull(valid_upto, '2500-12-31')"""
 
+	if args.get('posting_date'):
+		conditions += """ and %(posting_date)s between
+			ifnull(valid_from, '2000-01-01') and ifnull(valid_upto, '2500-12-31')"""
+
 	return frappe.db.sql(""" select name, price_list_rate, uom
 		from `tabItem Price` {conditions}
 		order by valid_from desc, uom desc """.format(conditions=conditions), args)
@@ -657,6 +686,7 @@
 			"supplier": args.get('supplier'),
 			"uom": args.get('uom'),
 			"transaction_date": args.get('transaction_date'),
+			"posting_date": args.get('posting_date'),
 	}
 
 	item_price_data = 0
diff --git a/erpnext/stock/module_onboarding/stock/stock.json b/erpnext/stock/module_onboarding/stock/stock.json
index de24575..1d5bf8c 100644
--- a/erpnext/stock/module_onboarding/stock/stock.json
+++ b/erpnext/stock/module_onboarding/stock/stock.json
@@ -19,7 +19,7 @@
  "documentation_url": "https://docs.erpnext.com/docs/user/manual/en/stock",
  "idx": 0,
  "is_complete": 0,
- "modified": "2020-05-19 19:03:23.602423",
+ "modified": "2020-07-08 14:22:07.951891",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Stock",
@@ -32,23 +32,22 @@
    "step": "Create a Product"
   },
   {
+   "step": "Create a Supplier"
+  },
+  {
    "step": "Introduction to Stock Entry"
   },
   {
    "step": "Create a Stock Entry"
   },
   {
-   "step": "Create a Supplier"
-  },
-  {
    "step": "Create a Purchase Receipt"
   },
   {
    "step": "Stock Settings"
   }
  ],
- "subtitle": "Inventory, Warehouses, Analysis and more.",
+ "subtitle": "Inventory, Warehouses, Analysis, and more.",
  "success_message": "The Stock Module is all set up!",
- "title": "Let's Setup the Stock Module.",
- "user_can_dismiss": 1
+ "title": "Let's Set Up the Stock Module."
 }
\ No newline at end of file
diff --git a/erpnext/stock/number_card/total_active_items/total_active_items.json b/erpnext/stock/number_card/total_active_items/total_active_items.json
new file mode 100644
index 0000000..f6863b9
--- /dev/null
+++ b/erpnext/stock/number_card/total_active_items/total_active_items.json
@@ -0,0 +1,20 @@
+{
+ "creation": "2020-07-20 21:01:04.422436",
+ "docstatus": 0,
+ "doctype": "Number Card",
+ "document_type": "Item",
+ "filters_json": "[[\"Item\",\"disabled\",\"=\",0]]",
+ "function": "Count",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "label": "Total Active Items",
+ "modified": "2020-07-22 13:08:30.430677",
+ "modified_by": "Administrator",
+ "module": "Stock",
+ "name": "Total Active Items",
+ "owner": "Administrator",
+ "show_percentage_stats": 1,
+ "stats_time_interval": "Monthly",
+ "type": "Document Type"
+}
\ No newline at end of file
diff --git a/erpnext/stock/number_card/total_stock_value/total_stock_value.json b/erpnext/stock/number_card/total_stock_value/total_stock_value.json
new file mode 100644
index 0000000..8e480a6
--- /dev/null
+++ b/erpnext/stock/number_card/total_stock_value/total_stock_value.json
@@ -0,0 +1,21 @@
+{
+ "aggregate_function_based_on": "stock_value",
+ "creation": "2020-07-20 21:01:04.495481",
+ "docstatus": 0,
+ "doctype": "Number Card",
+ "document_type": "Bin",
+ "filters_json": "[]",
+ "function": "Sum",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "label": "Total Stock Value",
+ "modified": "2020-07-22 13:08:48.412001",
+ "modified_by": "Administrator",
+ "module": "Stock",
+ "name": "Total Stock Value",
+ "owner": "Administrator",
+ "show_percentage_stats": 1,
+ "stats_time_interval": "Daily",
+ "type": "Document Type"
+}
\ No newline at end of file
diff --git a/erpnext/stock/number_card/total_warehouses/total_warehouses.json b/erpnext/stock/number_card/total_warehouses/total_warehouses.json
new file mode 100644
index 0000000..ab0836a
--- /dev/null
+++ b/erpnext/stock/number_card/total_warehouses/total_warehouses.json
@@ -0,0 +1,20 @@
+{
+ "creation": "2020-07-20 21:01:04.457598",
+ "docstatus": 0,
+ "doctype": "Number Card",
+ "document_type": "Warehouse",
+ "filters_json": "[[\"Warehouse\",\"disabled\",\"=\",0]]",
+ "function": "Count",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "label": "Total Warehouses",
+ "modified": "2020-07-22 13:08:40.258927",
+ "modified_by": "Administrator",
+ "module": "Stock",
+ "name": "Total Warehouses",
+ "owner": "Administrator",
+ "show_percentage_stats": 1,
+ "stats_time_interval": "Monthly",
+ "type": "Document Type"
+}
\ No newline at end of file
diff --git a/erpnext/stock/onboarding_step/setup_your_warehouse/setup_your_warehouse.json b/erpnext/stock/onboarding_step/setup_your_warehouse/setup_your_warehouse.json
index 557c905..9457dee 100644
--- a/erpnext/stock/onboarding_step/setup_your_warehouse/setup_your_warehouse.json
+++ b/erpnext/stock/onboarding_step/setup_your_warehouse/setup_your_warehouse.json
@@ -8,13 +8,13 @@
  "is_mandatory": 0,
  "is_single": 0,
  "is_skipped": 0,
- "modified": "2020-05-19 18:54:19.383397",
+ "modified": "2020-07-04 12:33:16.970031",
  "modified_by": "Administrator",
  "name": "Setup your Warehouse",
  "owner": "Administrator",
  "path": "Tree/Warehouse",
  "reference_document": "Warehouse",
  "show_full_form": 0,
- "title": "Setup your Warehouse",
+ "title": "Set up your Warehouse",
  "validate_action": 1
 }
\ No newline at end of file
diff --git a/erpnext/stock/report/stock_ageing/stock_ageing.py b/erpnext/stock/report/stock_ageing/stock_ageing.py
index 723ed5c..d5878cb 100644
--- a/erpnext/stock/report/stock_ageing/stock_ageing.py
+++ b/erpnext/stock/report/stock_ageing/stock_ageing.py
@@ -187,7 +187,7 @@
 						transferred_item_details[(d.voucher_no, d.name)].append(fifo_queue.pop(0))
 					else:
 						# all from current batch
-						batch[0] -= qty_to_pop
+						batch[0] = flt(batch[0]) - qty_to_pop
 						transferred_item_details[(d.voucher_no, d.name)].append([qty_to_pop, batch[1]])
 						qty_to_pop = 0
 
diff --git a/erpnext/stock/report/stock_balance/stock_balance.py b/erpnext/stock/report/stock_balance/stock_balance.py
index 74a4f6e..042087a 100644
--- a/erpnext/stock/report/stock_balance/stock_balance.py
+++ b/erpnext/stock/report/stock_balance/stock_balance.py
@@ -2,7 +2,7 @@
 # License: GNU General Public License v3. See license.txt
 
 from __future__ import unicode_literals
-import frappe
+import frappe, erpnext
 from frappe import _
 from frappe.utils import flt, cint, getdate, now, date_diff
 from erpnext.stock.utils import add_additional_uom_columns
@@ -20,6 +20,11 @@
 	from_date = filters.get('from_date')
 	to_date = filters.get('to_date')
 
+	if filters.get("company"):
+		company_currency = erpnext.get_company_currency(filters.get("company"))
+	else:
+		company_currency = frappe.db.get_single_value("Global Defaults", "default_currency")
+
 	include_uom = filters.get("include_uom")
 	columns = get_columns(filters)
 	items = get_items(filters)
@@ -52,6 +57,7 @@
 				item_reorder_qty = item_reorder_detail_map[item + warehouse]["warehouse_reorder_qty"]
 
 			report_data = {
+				'currency': company_currency,
 				'item_code': item,
 				'warehouse': warehouse,
 				'company': company,
@@ -89,7 +95,6 @@
 
 def get_columns(filters):
 	"""return columns"""
-
 	columns = [
 		{"label": _("Item"), "fieldname": "item_code", "fieldtype": "Link", "options": "Item", "width": 100},
 		{"label": _("Item Name"), "fieldname": "item_name", "width": 150},
@@ -97,14 +102,14 @@
 		{"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"},
-		{"label": _("Balance Value"), "fieldname": "bal_val", "fieldtype": "Currency", "width": 100},
+		{"label": _("Balance Value"), "fieldname": "bal_val", "fieldtype": "Currency", "width": 100, "options": "currency"},
 		{"label": _("Opening Qty"), "fieldname": "opening_qty", "fieldtype": "Float", "width": 100, "convertible": "qty"},
-		{"label": _("Opening Value"), "fieldname": "opening_val", "fieldtype": "Float", "width": 110},
+		{"label": _("Opening Value"), "fieldname": "opening_val", "fieldtype": "Currency", "width": 110, "options": "currency"},
 		{"label": _("In Qty"), "fieldname": "in_qty", "fieldtype": "Float", "width": 80, "convertible": "qty"},
 		{"label": _("In Value"), "fieldname": "in_val", "fieldtype": "Float", "width": 80},
 		{"label": _("Out Qty"), "fieldname": "out_qty", "fieldtype": "Float", "width": 80, "convertible": "qty"},
 		{"label": _("Out Value"), "fieldname": "out_val", "fieldtype": "Float", "width": 80},
-		{"label": _("Valuation Rate"), "fieldname": "val_rate", "fieldtype": "Currency", "width": 90, "convertible": "rate"},
+		{"label": _("Valuation Rate"), "fieldname": "val_rate", "fieldtype": "Currency", "width": 90, "convertible": "rate", "options": "currency"},
 		{"label": _("Reorder Level"), "fieldname": "reorder_level", "fieldtype": "Float", "width": 80, "convertible": "qty"},
 		{"label": _("Reorder Qty"), "fieldname": "reorder_qty", "fieldtype": "Float", "width": 80, "convertible": "qty"},
 		{"label": _("Company"), "fieldname": "company", "fieldtype": "Link", "options": "Company", "width": 100}
diff --git a/erpnext/stock/report/stock_ledger/stock_ledger.py b/erpnext/stock/report/stock_ledger/stock_ledger.py
index abf959e..fe8ad71 100644
--- a/erpnext/stock/report/stock_ledger/stock_ledger.py
+++ b/erpnext/stock/report/stock_ledger/stock_ledger.py
@@ -4,10 +4,10 @@
 from __future__ import unicode_literals
 
 import frappe
+from frappe.utils import cint, flt
 from erpnext.stock.utils import update_included_uom_in_report
 from frappe import _
 
-
 def execute(filters=None):
 	include_uom = filters.get("include_uom")
 	columns = get_columns()
@@ -15,6 +15,7 @@
 	sl_entries = get_stock_ledger_entries(filters, items)
 	item_details = get_item_details(items, sl_entries, include_uom)
 	opening_row = get_opening_balance(filters, columns)
+	precision = cint(frappe.db.get_single_value("System Settings", "float_precision"))
 
 	data = []
 	conversion_factors = []
@@ -29,10 +30,10 @@
 		sle.update(item_detail)
 
 		if filters.get("batch_no"):
-			actual_qty += sle.actual_qty
+			actual_qty += flt(sle.actual_qty, precision)
 			stock_value += sle.stock_value_difference
 
-			if sle.voucher_type == 'Stock Reconciliation':
+			if sle.voucher_type == 'Stock Reconciliation' and not sle.actual_qty:
 				actual_qty = sle.qty_after_transaction
 				stock_value = sle.stock_value
 
diff --git a/erpnext/stock/report/supplier_wise_sales_analytics/supplier_wise_sales_analytics.py b/erpnext/stock/report/supplier_wise_sales_analytics/supplier_wise_sales_analytics.py
index 6a86889..5873a7a 100644
--- a/erpnext/stock/report/supplier_wise_sales_analytics/supplier_wise_sales_analytics.py
+++ b/erpnext/stock/report/supplier_wise_sales_analytics/supplier_wise_sales_analytics.py
@@ -21,7 +21,7 @@
 			for cd in consumed_details.get(item_code):
 
 				if (cd.voucher_no not in material_transfer_vouchers):
-					if cd.voucher_type=="Delivery Note":
+					if cd.voucher_type in ["Delivery Note", "Sales Invoice"]:
 						delivered_qty += abs(flt(cd.actual_qty))
 						delivered_amount += abs(flt(cd.stock_value_difference))
 					elif cd.voucher_type!="Delivery Note":
diff --git a/erpnext/stock/stock_dashboard/stock/stock.json b/erpnext/stock/stock_dashboard/stock/stock.json
new file mode 100644
index 0000000..dee7fed
--- /dev/null
+++ b/erpnext/stock/stock_dashboard/stock/stock.json
@@ -0,0 +1,47 @@
+{
+ "cards": [
+  {
+   "card": "Total Active Items"
+  },
+  {
+   "card": "Total Warehouses"
+  },
+  {
+   "card": "Total Stock Value"
+  }
+ ],
+ "charts": [
+  {
+   "chart": "Warehouse wise Stock Value",
+   "width": "Full"
+  },
+  {
+   "chart": "Purchase Receipt Trends",
+   "width": "Half"
+  },
+  {
+   "chart": "Delivery Trends",
+   "width": "Half"
+  },
+  {
+   "chart": "Oldest Items",
+   "width": "Half"
+  },
+  {
+   "chart": "Item Shortage Summary",
+   "width": "Half"
+  }
+ ],
+ "creation": "2020-07-20 21:01:04.549136",
+ "dashboard_name": "Stock",
+ "docstatus": 0,
+ "doctype": "Dashboard",
+ "idx": 0,
+ "is_default": 1,
+ "is_standard": 1,
+ "modified": "2020-07-22 13:09:33.096694",
+ "modified_by": "Administrator",
+ "module": "Stock",
+ "name": "Stock",
+ "owner": "Administrator"
+}
\ No newline at end of file
diff --git a/erpnext/support/doctype/issue/issue.js b/erpnext/support/doctype/issue/issue.js
index e7e5bd3..9e15757 100644
--- a/erpnext/support/doctype/issue/issue.js
+++ b/erpnext/support/doctype/issue/issue.js
@@ -79,7 +79,7 @@
 					method: "erpnext.support.doctype.issue.issue.make_task",
 					frm: frm
 				});
-			}, __("Make"));
+			}, __("Create"));
 
 		} else {
 			if (frm.doc.service_level_agreement) {
@@ -232,4 +232,4 @@
 	} else {
 		return {"diff_display": "Failed", "indicator": "red"};
 	}
-}
\ No newline at end of file
+}
diff --git a/erpnext/support/doctype/issue/issue.py b/erpnext/support/doctype/issue/issue.py
index 883e603..87168e1 100644
--- a/erpnext/support/doctype/issue/issue.py
+++ b/erpnext/support/doctype/issue/issue.py
@@ -79,47 +79,52 @@
 
 	def handle_hold_time(self, status):
 		if self.service_level_agreement:
-			# set response and resolution variance as None as the issue is on Hold for status as Replied
+			# set response and resolution variance as None as the issue is on Hold
 			pause_sla_on = frappe.db.get_all("Pause SLA On Status", fields=["status"],
 				filters={"parent": self.service_level_agreement})
 			hold_statuses = [entry.status for entry in pause_sla_on]
 			update_values = {}
 
-			if self.status in hold_statuses and status not in hold_statuses:
-				update_values['on_hold_since'] = frappe.flags.current_time or now_datetime()
-				if not self.first_responded_on:
-					update_values['response_by'] = None
-					update_values['response_by_variance'] = 0
-				update_values['resolution_by'] = None
-				update_values['resolution_by_variance'] = 0
+			if hold_statuses:
+				if self.status in hold_statuses and status not in hold_statuses:
+					update_values['on_hold_since'] = frappe.flags.current_time or now_datetime()
+					if not self.first_responded_on:
+						update_values['response_by'] = None
+						update_values['response_by_variance'] = 0
+					update_values['resolution_by'] = None
+					update_values['resolution_by_variance'] = 0
 
-			# calculate hold time when status is changed from Replied to any other status
-			if self.status not in hold_statuses and status in hold_statuses:
-				hold_time = self.total_hold_time if self.total_hold_time else 0
-				now_time = frappe.flags.current_time or now_datetime()
-				update_values['total_hold_time'] = hold_time + time_diff_in_seconds(now_time, self.on_hold_since)
+				# calculate hold time when status is changed from any hold status to any non-hold status
+				if self.status not in hold_statuses and status in hold_statuses:
+					hold_time = self.total_hold_time if self.total_hold_time else 0
+					now_time = frappe.flags.current_time or now_datetime()
+					last_hold_time = 0
+					if self.on_hold_since:
+						# last_hold_time will be added to the sla variables
+						last_hold_time = time_diff_in_seconds(now_time, self.on_hold_since)
+						update_values['total_hold_time'] = hold_time + last_hold_time
 
-			# re-calculate SLA variables after issue changes from Replied to Open
-			# add hold time to SLA variables
-			if self.status == "Open" and status in hold_statuses:
-				start_date_time = get_datetime(self.service_level_agreement_creation)
-				priority = get_priority(self)
-				now_time = frappe.flags.current_time or now_datetime()
-				hold_time = time_diff_in_seconds(now_time, self.on_hold_since)
+					# re-calculate SLA variables after issue changes from any hold status to any non-hold status
+					# add hold time to SLA variables
+					start_date_time = get_datetime(self.service_level_agreement_creation)
+					priority = get_priority(self)
+					now_time = frappe.flags.current_time or now_datetime()
 
-				if not self.first_responded_on:
-					response_by = get_expected_time_for(parameter="response", service_level=priority, start_date_time=start_date_time)
-					update_values['response_by'] = add_to_date(response_by, seconds=round(hold_time))
-					response_by_variance = round(time_diff_in_hours(self.response_by, now_time))
-					update_values['response_by_variance'] = response_by_variance + (hold_time // 3600)
+					if not self.first_responded_on:
+						response_by = get_expected_time_for(parameter="response", service_level=priority, start_date_time=start_date_time)
+						response_by = add_to_date(response_by, seconds=round(last_hold_time))
+						response_by_variance = round(time_diff_in_hours(response_by, now_time))
+						update_values['response_by'] = response_by
+						update_values['response_by_variance'] = response_by_variance + (last_hold_time // 3600)
 
-				resolution_by = get_expected_time_for(parameter="resolution", service_level=priority, start_date_time=start_date_time)
-				update_values['resolution_by'] = add_to_date(resolution_by, seconds=round(hold_time))
-				resolution_by_variance = round(time_diff_in_hours(self.resolution_by, now_time))
-				update_values['resolution_by_variance'] = resolution_by_variance + (hold_time // 3600)
-				update_values['on_hold_since'] = None
+					resolution_by = get_expected_time_for(parameter="resolution", service_level=priority, start_date_time=start_date_time)
+					resolution_by = add_to_date(resolution_by, seconds=round(last_hold_time))
+					resolution_by_variance = round(time_diff_in_hours(resolution_by, now_time))
+					update_values['resolution_by'] = resolution_by
+					update_values['resolution_by_variance'] = resolution_by_variance + (last_hold_time // 3600)
+					update_values['on_hold_since'] = None
 
-			self.db_set(update_values)
+				self.db_set(update_values)
 
 	def update_agreement_status(self):
 		if self.service_level_agreement and self.agreement_fulfilled == "Ongoing":
diff --git a/erpnext/support/doctype/issue/issue_list.js b/erpnext/support/doctype/issue/issue_list.js
index 6d702f6..513a8dc 100644
--- a/erpnext/support/doctype/issue/issue_list.js
+++ b/erpnext/support/doctype/issue/issue_list.js
@@ -8,11 +8,11 @@
 
 		var method = "erpnext.support.doctype.issue.issue.set_multiple_status";
 
-		listview.page.add_menu_item(__("Set as Open"), function() {
+		listview.page.add_action_item(__("Set as Open"), function() {
 			listview.call_for_selected_items(method, {"status": "Open"});
 		});
 
-		listview.page.add_menu_item(__("Set as Closed"), function() {
+		listview.page.add_action_item(__("Set as Closed"), function() {
 			listview.call_for_selected_items(method, {"status": "Closed"});
 		});
 	},
diff --git a/erpnext/support/doctype/service_level_agreement/service_level_agreement.py b/erpnext/support/doctype/service_level_agreement/service_level_agreement.py
index c692315..70c4696 100644
--- a/erpnext/support/doctype/service_level_agreement/service_level_agreement.py
+++ b/erpnext/support/doctype/service_level_agreement/service_level_agreement.py
@@ -6,7 +6,7 @@
 import frappe
 from frappe.model.document import Document
 from frappe import _
-from frappe.utils import getdate, get_weekdays
+from frappe.utils import getdate, get_weekdays, get_link_to_form
 
 class ServiceLevelAgreement(Document):
 
@@ -21,8 +21,8 @@
 
 		for priority in self.priorities:
 			# Check if response and resolution time is set for every priority
-			if not (priority.response_time or priority.resolution_time):
-				frappe.throw(_("Set Response Time and Resolution for Priority {0} at index {1}.").format(priority.priority, priority.idx))
+			if not priority.response_time or not priority.resolution_time:
+				frappe.throw(_("Set Response Time and Resolution Time for Priority {0} in row {1}.").format(priority.priority, priority.idx))
 
 			priorities.append(priority.priority)
 
@@ -33,7 +33,7 @@
 			resolution = priority.resolution_time
 
 			if response > resolution:
-				frappe.throw(_("Response Time for {0} at index {1} can't be greater than Resolution Time.").format(priority.priority, priority.idx))
+				frappe.throw(_("Response Time for {0} priority in row {1} can't be greater than Resolution Time.").format(priority.priority, priority.idx))
 
 		# Check if repeated priority
 		if not len(set(priorities)) == len(priorities):
@@ -73,8 +73,9 @@
 			frappe.throw(_("Workday {0} has been repeated.").format(repeated_days))
 
 	def validate_doc(self):
-		if not frappe.db.get_single_value("Support Settings", "track_service_level_agreement"):
-			frappe.throw(_("Service Level Agreement tracking is not enabled."))
+		if not frappe.db.get_single_value("Support Settings", "track_service_level_agreement") and self.enable:
+			frappe.throw(_("{0} is not enabled in {1}").format(frappe.bold("Track Service Level Agreement"),
+				get_link_to_form("Support Settings", "Support Settings")))
 
 		if self.default_service_level_agreement:
 			if frappe.db.exists("Service Level Agreement", {"default_service_level_agreement": "1", "name": ["!=", self.name]}):
diff --git a/erpnext/templates/generators/item/item_configure.html b/erpnext/templates/generators/item/item_configure.html
index 04f89ec..b8b0d98 100644
--- a/erpnext/templates/generators/item/item_configure.html
+++ b/erpnext/templates/generators/item/item_configure.html
@@ -2,7 +2,7 @@
 {% set cart_settings = shopping_cart.cart_settings %}
 
 <div class="mt-3">
-	{% if cart_settings.show_configure_button | int %}
+	{% if cart_settings.enable_variants | int %}
 	<button class="btn btn-primary btn-configure"
 		data-item-code="{{ doc.name }}"
 		data-item-name="{{ doc.item_name }}"
diff --git a/erpnext/templates/includes/footer/footer_extension.html b/erpnext/templates/includes/footer/footer_extension.html
index 8cf3081..6171b61 100644
--- a/erpnext/templates/includes/footer/footer_extension.html
+++ b/erpnext/templates/includes/footer/footer_extension.html
@@ -6,7 +6,7 @@
 		aria-label="{{ _('Your email address...') }}"
 		aria-describedby="footer-subscribe-button">
 	<div class="input-group-append">
-		<button class="btn btn-outline-secondary"
+		<button class="btn btn-sm btn-outline-secondary"
 			type="button" id="footer-subscribe-button">{{ _("Get Updates") }}</button>
 	</div>
 </div>
diff --git a/erpnext/templates/includes/footer/footer_powered.html b/erpnext/templates/includes/footer/footer_powered.html
index 4274ba1..82b2716 100644
--- a/erpnext/templates/includes/footer/footer_powered.html
+++ b/erpnext/templates/includes/footer/footer_powered.html
@@ -12,8 +12,9 @@
 } %}
 
 {% set link = '' %}
-{% set label = domains[0].domain %}
+{% set label = '' %}
 {% if domains %}
+	{% set label = domains[0].domain %}
 	{% set link = links[label] %}
 {% endif %}
 
diff --git a/erpnext/accounts/page/pos/__init__.py b/erpnext/utilities/doctype/video/__init__.py
similarity index 100%
copy from erpnext/accounts/page/pos/__init__.py
copy to erpnext/utilities/doctype/video/__init__.py
diff --git a/erpnext/utilities/doctype/video/test_video.py b/erpnext/utilities/doctype/video/test_video.py
new file mode 100644
index 0000000..33ea31c
--- /dev/null
+++ b/erpnext/utilities/doctype/video/test_video.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 TestVideo(unittest.TestCase):
+	pass
diff --git a/erpnext/utilities/doctype/video/video.js b/erpnext/utilities/doctype/video/video.js
new file mode 100644
index 0000000..056bd3c
--- /dev/null
+++ b/erpnext/utilities/doctype/video/video.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('Video', {
+	// refresh: function(frm) {
+
+	// }
+});
diff --git a/erpnext/utilities/doctype/video/video.json b/erpnext/utilities/doctype/video/video.json
new file mode 100644
index 0000000..5d2cc13
--- /dev/null
+++ b/erpnext/utilities/doctype/video/video.json
@@ -0,0 +1,106 @@
+{
+ "actions": [],
+ "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": "provider",
+   "fieldtype": "Select",
+   "in_list_view": 1,
+   "label": "Provider",
+   "options": "YouTube\nVimeo",
+   "reqd": 1
+  },
+  {
+   "fieldname": "url",
+   "fieldtype": "Data",
+   "in_list_view": 1,
+   "label": "URL",
+   "reqd": 1
+  },
+  {
+   "fieldname": "column_break_4",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "publish_date",
+   "fieldtype": "Date",
+   "label": "Publish Date"
+  },
+  {
+   "fieldname": "duration",
+   "fieldtype": "Data",
+   "label": "Duration"
+  },
+  {
+   "fieldname": "section_break_7",
+   "fieldtype": "Section Break"
+  },
+  {
+   "fieldname": "description",
+   "fieldtype": "Text Editor",
+   "in_list_view": 1,
+   "label": "Description",
+   "reqd": 1
+  }
+ ],
+ "links": [],
+ "modified": "2020-07-21 19:29:46.603734",
+ "modified_by": "Administrator",
+ "module": "Utilities",
+ "name": "Video",
+ "owner": "Administrator",
+ "permissions": [
+  {
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "export": 1,
+   "if_owner": 1,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "All",
+   "share": 1,
+   "write": 1
+  },
+  {
+   "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/selling/doctype/pos_closing_voucher_taxes/pos_closing_voucher_taxes.py b/erpnext/utilities/doctype/video/video.py
similarity index 61%
copy from erpnext/selling/doctype/pos_closing_voucher_taxes/pos_closing_voucher_taxes.py
copy to erpnext/utilities/doctype/video/video.py
index 87ce842..3c17b56 100644
--- a/erpnext/selling/doctype/pos_closing_voucher_taxes/pos_closing_voucher_taxes.py
+++ b/erpnext/utilities/doctype/video/video.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 POSClosingVoucherTaxes(Document):
+class Video(Document):
 	pass
diff --git a/erpnext/utilities/transaction_base.py b/erpnext/utilities/transaction_base.py
index 2359648..c8e3330 100644
--- a/erpnext/utilities/transaction_base.py
+++ b/erpnext/utilities/transaction_base.py
@@ -120,6 +120,15 @@
 
 
 	def validate_rate_with_reference_doc(self, ref_details):
+		buying_doctypes = ["Purchase Order", "Purchase Invoice", "Purchase Receipt"]
+
+		if self.doctype in buying_doctypes:
+			to_disable = "Maintain same rate throughout Purchase cycle"
+			settings_page = "Buying Settings"
+		else:
+			to_disable = "Maintain same rate throughout Sales cycle"
+			settings_page = "Selling Settings"
+
 		for ref_dt, ref_dn_field, ref_link_field in ref_details:
 			for d in self.get("items"):
 				if d.get(ref_link_field):
@@ -129,8 +138,8 @@
 						frappe.msgprint(_("Row #{0}: Rate must be same as {1}: {2} ({3} / {4}) ")
 							.format(d.idx, ref_dt, d.get(ref_dn_field), d.rate, ref_rate))
 						frappe.throw(_("To allow different rates, disable the {0} checkbox in {1}.")
-							.format(frappe.bold(_("Maintain Same Rate Throughout Sales Cycle")),
-							get_link_to_form("Selling Settings", "Selling Settings", frappe.bold("Selling Settings"))))
+							.format(frappe.bold(_(to_disable)),
+							get_link_to_form(settings_page, settings_page, frappe.bold(settings_page))))
 
 	def get_link_filters(self, for_doctype):
 		if hasattr(self, "prev_link_mapper") and self.prev_link_mapper.get(for_doctype):
diff --git a/requirements.txt b/requirements.txt
index 9da537e..912d61f 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -2,10 +2,12 @@
 frappe
 gocardless-pro==1.11.0
 googlemaps==3.1.1
-pandas==0.24.2
+pandas==1.0.5
 plaid-python==3.4.0
+pycountry==19.8.18
 PyGithub==1.44.1
 python-stdnum==1.12
+taxjar==1.9.0
+tweepy==3.8.0
 Unidecode==1.1.1
 WooCommerce==2.1.1
-tweepy==3.8.0
\ No newline at end of file