Merge branch 'develop' of https://github.com/frappe/erpnext into loan_patch_fix
diff --git a/.eslintrc b/.eslintrc
index 757aa3c..d6f0f49 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -5,7 +5,7 @@
 		"es6": true
 	},
 	"parserOptions": {
-		"ecmaVersion": 6,
+		"ecmaVersion": 9,
 		"sourceType": "module"
 	},
 	"extends": "eslint:recommended",
@@ -15,6 +15,14 @@
 			"tab",
 			{ "SwitchCase": 1 }
 		],
+		"brace-style": [
+			"error",
+			"1tbs"
+		],
+		"space-unary-ops": [
+			"error",
+			{ "words": true }
+		],
 		"linebreak-style": [
 			"error",
 			"unix"
@@ -44,12 +52,10 @@
 		"no-control-regex": [
 			"off"
 		],
-		"spaced-comment": [
-			"warn"
-		],
-		"no-trailing-spaces": [
-			"warn"
-		]
+		"space-before-blocks": "warn",
+		"keyword-spacing": "warn",
+		"comma-spacing": "warn",
+		"key-spacing": "warn"
 	},
 	"root": true,
 	"globals": {
diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml
new file mode 100644
index 0000000..26bb7ab
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/config.yml
@@ -0,0 +1,5 @@
+blank_issues_enabled: false
+contact_links:
+  - name: Community Forum
+    url: https://discuss.erpnext.com/
+    about: For general QnA, discussions and community help.
diff --git a/README.md b/README.md
index 0f6a521..15782a2 100644
--- a/README.md
+++ b/README.md
@@ -5,7 +5,7 @@
         <p>ERP made simple</p>
     </p>
 
-[![Build Status](https://travis-ci.com/frappe/erpnext.svg)](https://travis-ci.com/frappe/erpnext)
+[![Build Status](https://api.travis-ci.com/frappe/erpnext.svg?branch=develop)](https://travis-ci.com/frappe/erpnext)
 [![Open Source Helpers](https://www.codetriage.com/frappe/erpnext/badges/users.svg)](https://www.codetriage.com/frappe/erpnext)
 [![Coverage Status](https://coveralls.io/repos/github/frappe/erpnext/badge.svg?branch=develop)](https://coveralls.io/github/frappe/erpnext?branch=develop)
 
diff --git a/erpnext/accounts/dashboard_chart_source/account_balance_timeline/account_balance_timeline.py b/erpnext/accounts/dashboard_chart_source/account_balance_timeline/account_balance_timeline.py
index 39bf4b0..85f54f9 100644
--- a/erpnext/accounts/dashboard_chart_source/account_balance_timeline/account_balance_timeline.py
+++ b/erpnext/accounts/dashboard_chart_source/account_balance_timeline/account_balance_timeline.py
@@ -6,9 +6,8 @@
 from frappe import _
 from frappe.utils import add_to_date, date_diff, getdate, nowdate, get_last_day, formatdate, get_link_to_form
 from erpnext.accounts.report.general_ledger.general_ledger import execute
-from frappe.utils.dashboard import cache_source, get_from_date_from_timespan
-from frappe.desk.doctype.dashboard_chart.dashboard_chart import get_period_ending
-
+from frappe.utils.dashboard import cache_source
+from frappe.utils.dateutils import get_from_date_from_timespan, get_period_ending
 from frappe.utils.nestedset import get_descendants_of
 
 @frappe.whitelist()
diff --git a/erpnext/accounts/desk_page/accounting/accounting.json b/erpnext/accounts/desk_page/accounting/accounting.json
index b0371e7..a18dbff 100644
--- a/erpnext/accounts/desk_page/accounting/accounting.json
+++ b/erpnext/accounts/desk_page/accounting/accounting.json
@@ -23,7 +23,7 @@
   {
    "hidden": 0,
    "label": "Reports",
-   "links": "[\n    {\n        \"dependencies\": [\n            \"GL Entry\"\n        ],\n        \"doctype\": \"GL Entry\",\n        \"is_query_report\": true,\n        \"label\": \"Trial Balance for Party\",\n        \"name\": \"Trial Balance for Party\",\n        \"type\": \"report\"\n    },\n    {\n        \"dependencies\": [\n            \"Journal Entry\"\n        ],\n        \"doctype\": \"Journal Entry\",\n        \"is_query_report\": true,\n        \"label\": \"Payment Period Based On Invoice Date\",\n        \"name\": \"Payment Period Based On Invoice Date\",\n        \"type\": \"report\"\n    },\n    {\n        \"dependencies\": [\n            \"Sales Invoice\"\n        ],\n        \"doctype\": \"Sales Invoice\",\n        \"is_query_report\": true,\n        \"label\": \"Sales Partners Commission\",\n        \"name\": \"Sales Partners Commission\",\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            \"Sales Invoice\"\n        ],\n        \"doctype\": \"Sales Invoice\",\n        \"is_query_report\": true,\n        \"label\": \"Sales Payment Summary\",\n        \"name\": \"Sales Payment Summary\",\n        \"type\": \"report\"\n    },\n    {\n        \"dependencies\": [\n            \"Address\"\n        ],\n        \"doctype\": \"Address\",\n        \"is_query_report\": true,\n        \"label\": \"Address And Contacts\",\n        \"name\": \"Address And Contacts\",\n        \"type\": \"report\"\n    }\n]"
+   "links": "[\n    {\n        \"dependencies\": [\n            \"GL Entry\"\n        ],\n        \"doctype\": \"GL Entry\",\n        \"is_query_report\": true,\n        \"label\": \"Trial Balance for Party\",\n        \"name\": \"Trial Balance for Party\",\n        \"type\": \"report\"\n    },\n    {\n        \"dependencies\": [\n            \"Journal Entry\"\n        ],\n        \"doctype\": \"Journal Entry\",\n        \"is_query_report\": true,\n        \"label\": \"Payment Period Based On Invoice Date\",\n        \"name\": \"Payment Period Based On Invoice Date\",\n        \"type\": \"report\"\n    },\n    {\n        \"dependencies\": [\n            \"Sales Invoice\"\n        ],\n        \"doctype\": \"Sales Invoice\",\n        \"is_query_report\": true,\n        \"label\": \"Sales Partners Commission\",\n        \"name\": \"Sales Partners Commission\",\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            \"Sales Invoice\"\n        ],\n        \"doctype\": \"Sales Invoice\",\n        \"is_query_report\": true,\n        \"label\": \"Sales Payment Summary\",\n        \"name\": \"Sales Payment Summary\",\n        \"type\": \"report\"\n    },\n    {\n        \"dependencies\": [\n            \"Address\"\n        ],\n        \"doctype\": \"Address\",\n        \"is_query_report\": true,\n        \"label\": \"Address And Contacts\",\n        \"name\": \"Address And Contacts\",\n        \"type\": \"report\"\n    },\n    {\n        \"dependencies\": [\n            \"GL Entry\"\n        ],\n        \"doctype\": \"GL Entry\",\n        \"is_query_report\": true,\n        \"label\": \"DATEV Export\",\n        \"name\": \"DATEV\",\n        \"type\": \"report\"\n    }\n]"
   },
   {
    "hidden": 0,
@@ -43,7 +43,7 @@
   {
    "hidden": 0,
    "label": "Bank Statement",
-   "links": "[\n    {\n        \"label\": \"Bank\",\n        \"name\": \"Bank\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"Bank Account\",\n        \"name\": \"Bank Account\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"Bank Statement Transaction Entry\",\n        \"name\": \"Bank Statement Transaction Entry\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"Bank Statement Settings\",\n        \"name\": \"Bank Statement Settings\",\n        \"type\": \"doctype\"\n    }\n]"
+   "links": "[\n    {\n        \"label\": \"Bank\",\n        \"name\": \"Bank\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"Bank Account\",\n        \"name\": \"Bank Account\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"Bank Clearance\",\n        \"name\": \"Bank Clearance\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"Bank Reconciliation\",\n        \"name\": \"bank-reconciliation\",\n        \"type\": \"page\"\n    },\n    {\n        \"dependencies\": [\n            \"GL Entry\"\n        ],\n        \"doctype\": \"GL Entry\",\n        \"is_query_report\": true,\n        \"label\": \"Bank Reconciliation Statement\",\n        \"name\": \"Bank Reconciliation Statement\",\n        \"type\": \"report\"\n    }\n]"
   },
   {
    "hidden": 0,
@@ -79,6 +79,11 @@
    "hidden": 0,
    "label": "Profitability",
    "links": "[\n    {\n        \"dependencies\": [\n            \"Sales Invoice\"\n        ],\n        \"doctype\": \"Sales Invoice\",\n        \"is_query_report\": true,\n        \"label\": \"Gross Profit\",\n        \"name\": \"Gross Profit\",\n        \"type\": \"report\"\n    },\n    {\n        \"dependencies\": [\n            \"GL Entry\"\n        ],\n        \"doctype\": \"GL Entry\",\n        \"is_query_report\": true,\n        \"label\": \"Profitability Analysis\",\n        \"name\": \"Profitability Analysis\",\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            \"Purchase Invoice\"\n        ],\n        \"doctype\": \"Purchase Invoice\",\n        \"is_query_report\": true,\n        \"label\": \"Purchase Invoice Trends\",\n        \"name\": \"Purchase Invoice Trends\",\n        \"type\": \"report\"\n    }\n]"
+  },
+  {
+   "hidden": 0,
+   "label": "Value-Added Tax (VAT UAE)",
+   "links": "[\n    {\n        \"country\": \"United Arab Emirates\",\n        \"label\": \"UAE VAT Settings\",\n        \"name\": \"UAE VAT Settings\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"country\": \"United Arab Emirates\",\n        \"is_query_report\": true,\n        \"label\": \"UAE VAT 201\",\n        \"name\": \"UAE VAT 201\",\n        \"type\": \"report\"\n    }\n\n]"
   }
  ],
  "category": "Modules",
@@ -98,7 +103,7 @@
  "idx": 0,
  "is_standard": 1,
  "label": "Accounting",
- "modified": "2020-10-08 20:31:46.022470",
+ "modified": "2020-11-11 18:35:11.542909",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "Accounting",
@@ -108,7 +113,7 @@
  "pin_to_top": 0,
  "shortcuts": [
   {
-   "label": "Chart of Accounts",
+   "label": "Chart Of Accounts",
    "link_to": "Account",
    "type": "DocType"
   },
diff --git a/erpnext/accounts/doctype/chart_of_accounts_importer/chart_of_accounts_importer.js b/erpnext/accounts/doctype/chart_of_accounts_importer/chart_of_accounts_importer.js
index 2235298..f795dfa 100644
--- a/erpnext/accounts/doctype/chart_of_accounts_importer/chart_of_accounts_importer.js
+++ b/erpnext/accounts/doctype/chart_of_accounts_importer/chart_of_accounts_importer.js
@@ -94,8 +94,7 @@
 				callback: function(r) {
 					if(r.message===false) {
 						frm.set_value("company", "");
-						frappe.throw(__(`Transactions against the company already exist!
-							Chart Of accounts can be imported for company with no transactions`));
+						frappe.throw(__("Transactions against the Company already exist! Chart of Accounts can only be imported for a Company with no transactions."));
 					} else {
 						frm.trigger("refresh");
 					}
diff --git a/erpnext/accounts/doctype/fiscal_year/fiscal_year.js b/erpnext/accounts/doctype/fiscal_year/fiscal_year.js
index 152e17d..bc77dac 100644
--- a/erpnext/accounts/doctype/fiscal_year/fiscal_year.js
+++ b/erpnext/accounts/doctype/fiscal_year/fiscal_year.js
@@ -9,11 +9,7 @@
 		}
 	},
 	refresh: function (frm) {
-		let doc = frm.doc;
-		frm.toggle_enable('year_start_date', doc.__islocal);
-		frm.toggle_enable('year_end_date', doc.__islocal);
-
-		if (!doc.__islocal && (doc.name != frappe.sys_defaults.fiscal_year)) {
+		if (!frm.doc.__islocal && (frm.doc.name != frappe.sys_defaults.fiscal_year)) {
 			frm.add_custom_button(__("Set as Default"), () => frm.events.set_as_default(frm));
 			frm.set_intro(__("To set this Fiscal Year as Default, click on 'Set as Default'"));
 		} else {
@@ -24,8 +20,10 @@
 		return frm.call('set_as_default');
 	},
 	year_start_date: function(frm) {
-		let year_end_date =
-			frappe.datetime.add_days(frappe.datetime.add_months(frm.doc.year_start_date, 12), -1);
-		frm.set_value("year_end_date", year_end_date);
+		if (!frm.doc.is_short_year) {
+			let year_end_date =
+				frappe.datetime.add_days(frappe.datetime.add_months(frm.doc.year_start_date, 12), -1);
+			frm.set_value("year_end_date", year_end_date);
+		}
 	},
 });
diff --git a/erpnext/accounts/doctype/fiscal_year/fiscal_year.json b/erpnext/accounts/doctype/fiscal_year/fiscal_year.json
index 4ca9f6b..5ab91f2 100644
--- a/erpnext/accounts/doctype/fiscal_year/fiscal_year.json
+++ b/erpnext/accounts/doctype/fiscal_year/fiscal_year.json
@@ -1,347 +1,126 @@
 {
- "allow_copy": 0, 
- "allow_guest_to_view": 0, 
- "allow_import": 1, 
- "allow_rename": 0, 
- "autoname": "field:year", 
- "beta": 0, 
- "creation": "2013-01-22 16:50:25", 
- "custom": 0, 
- "description": "**Fiscal Year** represents a Financial Year. All accounting entries and other major transactions are tracked against **Fiscal Year**.", 
- "docstatus": 0, 
- "doctype": "DocType", 
- "document_type": "Setup", 
- "editable_grid": 0, 
+ "actions": [],
+ "allow_import": 1,
+ "autoname": "field:year",
+ "creation": "2013-01-22 16:50:25",
+ "description": "**Fiscal Year** represents a Financial Year. All accounting entries and other major transactions are tracked against **Fiscal Year**.",
+ "doctype": "DocType",
+ "document_type": "Setup",
+ "engine": "InnoDB",
+ "field_order": [
+  "year",
+  "disabled",
+  "is_short_year",
+  "year_start_date",
+  "year_end_date",
+  "companies",
+  "auto_created"
+ ],
  "fields": [
   {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "description": "For e.g. 2012, 2012-13", 
-   "fieldname": "year", 
-   "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": "Year Name", 
-   "length": 0, 
-   "no_copy": 0, 
-   "oldfieldname": "year", 
-   "oldfieldtype": "Data", 
-   "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
-  }, 
+   "description": "For e.g. 2012, 2012-13",
+   "fieldname": "year",
+   "fieldtype": "Data",
+   "in_list_view": 1,
+   "label": "Year Name",
+   "oldfieldname": "year",
+   "oldfieldtype": "Data",
+   "reqd": 1,
+   "unique": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "disabled", 
-   "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": "Disabled", 
-   "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": "disabled",
+   "fieldtype": "Check",
+   "label": "Disabled"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "year_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": "Year Start Date", 
-   "length": 0, 
-   "no_copy": 1, 
-   "oldfieldname": "year_start_date", 
-   "oldfieldtype": "Date", 
-   "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
-  }, 
+   "fieldname": "year_start_date",
+   "fieldtype": "Date",
+   "in_list_view": 1,
+   "label": "Year Start Date",
+   "no_copy": 1,
+   "oldfieldname": "year_start_date",
+   "oldfieldtype": "Date",
+   "reqd": 1,
+   "set_only_once": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "year_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": "Year End Date", 
-   "length": 0, 
-   "no_copy": 1, 
-   "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
-  }, 
+   "fieldname": "year_end_date",
+   "fieldtype": "Date",
+   "in_list_view": 1,
+   "label": "Year End Date",
+   "no_copy": 1,
+   "reqd": 1,
+   "set_only_once": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "companies", 
-   "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": "Companies", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Fiscal Year 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": "companies",
+   "fieldtype": "Table",
+   "label": "Companies",
+   "options": "Fiscal Year Company"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "default": "0", 
-   "fieldname": "auto_created", 
-   "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": "Auto Created", 
-   "length": 0, 
-   "no_copy": 1, 
-   "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": "auto_created",
+   "fieldtype": "Check",
+   "hidden": 1,
+   "label": "Auto Created",
+   "no_copy": 1,
+   "print_hide": 1,
+   "read_only": 1
+  },
+  {
+   "default": "0",
+   "description": "Less than 12 months.",
+   "fieldname": "is_short_year",
+   "fieldtype": "Check",
+   "label": "Is Short Year",
+   "set_only_once": 1
   }
- ], 
- "has_web_view": 0, 
- "hide_heading": 0, 
- "hide_toolbar": 0, 
- "icon": "fa fa-calendar", 
- "idx": 1, 
- "image_view": 0, 
- "in_create": 0, 
- "is_submittable": 0, 
- "issingle": 0, 
- "istable": 0, 
- "max_attachments": 0, 
- "modified": "2018-04-25 14:21:41.273354", 
- "modified_by": "Administrator", 
- "module": "Accounts", 
- "name": "Fiscal Year", 
- "owner": "Administrator", 
+ ],
+ "icon": "fa fa-calendar",
+ "idx": 1,
+ "links": [],
+ "modified": "2020-11-05 12:16:53.081573",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "Fiscal Year",
+ "owner": "Administrator",
  "permissions": [
   {
-   "amend": 0, 
-   "cancel": 0, 
-   "create": 1, 
-   "delete": 1, 
-   "email": 1, 
-   "export": 0, 
-   "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,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "System Manager",
+   "share": 1,
    "write": 1
-  }, 
+  },
   {
-   "amend": 0, 
-   "cancel": 0, 
-   "create": 0, 
-   "delete": 0, 
-   "email": 0, 
-   "export": 0, 
-   "if_owner": 0, 
-   "import": 0, 
-   "permlevel": 0, 
-   "print": 0, 
-   "read": 1, 
-   "report": 0, 
-   "role": "Sales User", 
-   "set_user_permissions": 0, 
-   "share": 0, 
-   "submit": 0, 
-   "write": 0
-  }, 
+   "read": 1,
+   "role": "Sales User"
+  },
   {
-   "amend": 0, 
-   "cancel": 0, 
-   "create": 0, 
-   "delete": 0, 
-   "email": 0, 
-   "export": 0, 
-   "if_owner": 0, 
-   "import": 0, 
-   "permlevel": 0, 
-   "print": 0, 
-   "read": 1, 
-   "report": 0, 
-   "role": "Purchase User", 
-   "set_user_permissions": 0, 
-   "share": 0, 
-   "submit": 0, 
-   "write": 0
-  }, 
+   "read": 1,
+   "role": "Purchase User"
+  },
   {
-   "amend": 0, 
-   "cancel": 0, 
-   "create": 0, 
-   "delete": 0, 
-   "email": 0, 
-   "export": 0, 
-   "if_owner": 0, 
-   "import": 0, 
-   "permlevel": 0, 
-   "print": 0, 
-   "read": 1, 
-   "report": 0, 
-   "role": "Accounts User", 
-   "set_user_permissions": 0, 
-   "share": 0, 
-   "submit": 0, 
-   "write": 0
-  }, 
+   "read": 1,
+   "role": "Accounts User"
+  },
   {
-   "amend": 0, 
-   "cancel": 0, 
-   "create": 0, 
-   "delete": 0, 
-   "email": 0, 
-   "export": 0, 
-   "if_owner": 0, 
-   "import": 0, 
-   "permlevel": 0, 
-   "print": 0, 
-   "read": 1, 
-   "report": 0, 
-   "role": "Stock User", 
-   "set_user_permissions": 0, 
-   "share": 0, 
-   "submit": 0, 
-   "write": 0
-  }, 
+   "read": 1,
+   "role": "Stock User"
+  },
   {
-   "amend": 0, 
-   "cancel": 0, 
-   "create": 0, 
-   "delete": 0, 
-   "email": 0, 
-   "export": 0, 
-   "if_owner": 0, 
-   "import": 0, 
-   "permlevel": 0, 
-   "print": 0, 
-   "read": 1, 
-   "report": 0, 
-   "role": "Employee", 
-   "set_user_permissions": 0, 
-   "share": 0, 
-   "submit": 0, 
-   "write": 0
+   "read": 1,
+   "role": "Employee"
   }
- ], 
- "quick_entry": 0, 
- "read_only": 0, 
- "read_only_onload": 0, 
- "show_name_in_global_search": 1, 
- "sort_field": "name", 
- "sort_order": "DESC", 
- "track_changes": 0, 
- "track_seen": 0
+ ],
+ "show_name_in_global_search": 1,
+ "sort_field": "name",
+ "sort_order": "DESC"
 }
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/fiscal_year/fiscal_year.py b/erpnext/accounts/doctype/fiscal_year/fiscal_year.py
index d80bc7f..da6a3fd 100644
--- a/erpnext/accounts/doctype/fiscal_year/fiscal_year.py
+++ b/erpnext/accounts/doctype/fiscal_year/fiscal_year.py
@@ -36,6 +36,11 @@
 					frappe.throw(_("Cannot change Fiscal Year Start Date and Fiscal Year End Date once the Fiscal Year is saved."))
 
 	def validate_dates(self):
+		if self.is_short_year:
+			# Fiscal Year can be shorter than one year, in some jurisdictions
+			# under certain circumstances. For example, in the USA and Germany.
+			return
+
 		if getdate(self.year_start_date) > getdate(self.year_end_date):
 			frappe.throw(_("Fiscal Year Start Date should be one year earlier than Fiscal Year End Date"),
 				FiscalYearIncorrectDate)
@@ -116,12 +121,8 @@
 			pass
 
 def get_from_and_to_date(fiscal_year):
-	from_and_to_date_tuple = frappe.db.sql("""select year_start_date, year_end_date
-		from `tabFiscal Year` where name=%s""", (fiscal_year))[0]
-
-	from_and_to_date = {
-		"from_date": from_and_to_date_tuple[0],
-		"to_date": from_and_to_date_tuple[1]
-	}
-
-	return from_and_to_date
+	fields = [
+		"year_start_date as from_date",
+		"year_end_date as to_date"
+	]
+	return frappe.db.get_value("Fiscal Year", fiscal_year, fields, as_dict=1)
diff --git a/erpnext/accounts/doctype/fiscal_year/test_fiscal_year.py b/erpnext/accounts/doctype/fiscal_year/test_fiscal_year.py
index f7b7782..cec4f44 100644
--- a/erpnext/accounts/doctype/fiscal_year/test_fiscal_year.py
+++ b/erpnext/accounts/doctype/fiscal_year/test_fiscal_year.py
@@ -11,6 +11,7 @@
 test_ignore = ["Company"]
 
 class TestFiscalYear(unittest.TestCase):
+
 	def test_extra_year(self):
 		if frappe.db.exists("Fiscal Year", "_Test Fiscal Year 2000"):
 			frappe.delete_doc("Fiscal Year", "_Test Fiscal Year 2000")
diff --git a/erpnext/accounts/doctype/fiscal_year/test_records.json b/erpnext/accounts/doctype/fiscal_year/test_records.json
index d5723ca..4405253 100644
--- a/erpnext/accounts/doctype/fiscal_year/test_records.json
+++ b/erpnext/accounts/doctype/fiscal_year/test_records.json
@@ -1,6 +1,13 @@
 [
  {
   "doctype": "Fiscal Year",
+  "year": "_Test Short Fiscal Year 2011",
+  "is_short_year": 1,
+  "year_end_date": "2011-04-01",
+  "year_start_date": "2011-12-31"
+ },
+ {
+  "doctype": "Fiscal Year",
   "year": "_Test Fiscal Year 2012",
   "year_end_date": "2012-12-31",
   "year_start_date": "2012-01-01"
diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.json b/erpnext/accounts/doctype/journal_entry/journal_entry.json
index 4573c50..b7bbb74 100644
--- a/erpnext/accounts/doctype/journal_entry/journal_entry.json
+++ b/erpnext/accounts/doctype/journal_entry/journal_entry.json
@@ -1,5 +1,6 @@
 {
  "actions": [],
+ "allow_auto_repeat": 1,
  "allow_import": 1,
  "autoname": "naming_series:",
  "creation": "2013-03-25 10:53:52",
@@ -503,7 +504,7 @@
  "idx": 176,
  "is_submittable": 1,
  "links": [],
- "modified": "2020-06-02 18:15:46.955697",
+ "modified": "2020-10-30 13:56:01.121995",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "Journal Entry",
diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py
index d839478..ab4bfb1 100644
--- a/erpnext/accounts/doctype/journal_entry/journal_entry.py
+++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py
@@ -339,8 +339,7 @@
 						currency=account_currency)
 
 				if flt(voucher_total) < (flt(order.advance_paid) + total):
-					frappe.throw(_("Advance paid against {0} {1} cannot be greater \
-						than Grand Total {2}").format(reference_type, reference_name, formatted_voucher_total))
+					frappe.throw(_("Advance paid against {0} {1} cannot be greater than Grand Total {2}").format(reference_type, reference_name, formatted_voucher_total))
 
 	def validate_invoices(self):
 		"""Validate totals and docstatus for invoices"""
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.json b/erpnext/accounts/doctype/payment_entry/payment_entry.json
index 72149a6..2e1f201 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.json
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.json
@@ -1,5 +1,6 @@
 {
  "actions": [],
+ "allow_auto_repeat": 1,
  "allow_import": 1,
  "autoname": "naming_series:",
  "creation": "2016-06-01 14:38:51.012597",
@@ -587,7 +588,7 @@
  "index_web_pages_for_search": 1,
  "is_submittable": 1,
  "links": [],
- "modified": "2020-09-02 13:39:43.383705",
+ "modified": "2020-10-30 13:56:20.007336",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "Payment Entry",
diff --git a/erpnext/accounts/doctype/pos_invoice/pos_invoice.json b/erpnext/accounts/doctype/pos_invoice/pos_invoice.json
index 1cff3c6..5bc57b4 100644
--- a/erpnext/accounts/doctype/pos_invoice/pos_invoice.json
+++ b/erpnext/accounts/doctype/pos_invoice/pos_invoice.json
@@ -1,5 +1,6 @@
 {
  "actions": [],
+ "allow_auto_repeat": 1,
  "allow_import": 1,
  "autoname": "naming_series:",
  "creation": "2020-01-24 15:29:29.933693",
@@ -1580,7 +1581,7 @@
  "icon": "fa fa-file-text",
  "is_submittable": 1,
  "links": [],
- "modified": "2020-09-28 16:51:24.641755",
+ "modified": "2020-10-30 13:56:51.056083",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "POS Invoice",
diff --git a/erpnext/accounts/doctype/pos_invoice/pos_invoice.py b/erpnext/accounts/doctype/pos_invoice/pos_invoice.py
index b0a7547..d486ff6 100644
--- a/erpnext/accounts/doctype/pos_invoice/pos_invoice.py
+++ b/erpnext/accounts/doctype/pos_invoice/pos_invoice.py
@@ -39,6 +39,7 @@
 		self.validate_serialised_or_batched_item()
 		self.validate_stock_availablility()
 		self.validate_return_items_qty()
+		self.validate_non_stock_items()
 		self.set_status()
 		self.set_account_for_mode_of_payment()
 		self.validate_pos()
@@ -132,15 +133,19 @@
 
 			msg = ""
 			item_code = frappe.bold(d.item_code)
+			serial_nos = get_serial_nos(d.serial_no)
 			if serialized and batched and (no_batch_selected or no_serial_selected):
 				msg = (_('Row #{}: Please select a serial no and batch against item: {} or remove it to complete transaction.')
 							.format(d.idx, item_code))
-			if serialized and no_serial_selected:
+			elif serialized and no_serial_selected:
 				msg = (_('Row #{}: No serial number selected against item: {}. Please select one or remove it to complete transaction.')
 							.format(d.idx, item_code))
-			if batched and no_batch_selected:
+			elif batched and no_batch_selected:
 				msg = (_('Row #{}: No batch selected against item: {}. Please select a batch or remove it to complete transaction.')
 							.format(d.idx, item_code))
+			elif serialized and not no_serial_selected and len(serial_nos) != d.qty:
+				msg = (_("Row #{}: You must select {} serial numbers for item {}.").format(d.idx, frappe.bold(cint(d.qty)), item_code))
+
 			if msg:
 				error_msg.append(msg)
 
@@ -170,6 +175,14 @@
 							_("Row #{}: Serial No {} cannot be returned since it was not transacted in original invoice {}")
 							.format(d.idx, bold_serial_no, bold_return_against)
 						)
+	
+	def validate_non_stock_items(self):
+		for d in self.get("items"):
+			is_stock_item = frappe.get_cached_value("Item", d.get("item_code"), "is_stock_item")
+			if not is_stock_item:
+				frappe.throw(_("Row #{}: Item {} is a non stock item. You can only include stock items in a POS Invoice. ").format(
+					d.idx, frappe.bold(d.item_code)
+				), title=_("Invalid Item"))
 
 	def validate_mode_of_payment(self):
 		if len(self.payments) == 0:
diff --git a/erpnext/accounts/doctype/pos_profile/pos_profile.js b/erpnext/accounts/doctype/pos_profile/pos_profile.js
index 558e21c..7f4f755 100755
--- a/erpnext/accounts/doctype/pos_profile/pos_profile.js
+++ b/erpnext/accounts/doctype/pos_profile/pos_profile.js
@@ -35,6 +35,15 @@
 			};
 		});
 
+		frm.set_query("taxes_and_charges", function() {
+			return {
+				filters: [
+					['Sales Taxes and Charges Template', 'company', '=', frm.doc.company],
+					['Sales Taxes and Charges Template', 'docstatus', '!=', 2]
+				]
+			};
+		});
+
 		frm.set_query('company_address', function(doc) {
 			if(!doc.company) {
 				frappe.throw(__('Please set Company'));
diff --git a/erpnext/accounts/doctype/pricing_rule/pricing_rule.js b/erpnext/accounts/doctype/pricing_rule/pricing_rule.js
index c92b58b..d79ad5f 100644
--- a/erpnext/accounts/doctype/pricing_rule/pricing_rule.js
+++ b/erpnext/accounts/doctype/pricing_rule/pricing_rule.js
@@ -42,56 +42,56 @@
 				<tr><td>
 					<h4>
 						<i class="fa fa-hand-right"></i>
-						${__('Notes')}
+						{{__('Notes')}}
 					</h4>
 					<ul>
 						<li>
-							${__("Pricing Rule is made to overwrite Price List / define discount percentage, based on some criteria.")}
+							{{__("Pricing Rule is made to overwrite Price List / define discount percentage, based on some criteria.")}}
 						</li>
 						<li>
-							${__("If selected Pricing Rule is made for 'Rate', it will overwrite Price List. Pricing Rule rate is the final rate, so no further discount should be applied. Hence, in transactions like Sales Order, Purchase Order etc, it will be fetched in 'Rate' field, rather than 'Price List Rate' field.")}
+							{{__("If selected Pricing Rule is made for 'Rate', it will overwrite Price List. Pricing Rule rate is the final rate, so no further discount should be applied. Hence, in transactions like Sales Order, Purchase Order etc, it will be fetched in 'Rate' field, rather than 'Price List Rate' field.")}}
 						</li>
 						<li>
-							${__('Discount Percentage can be applied either against a Price List or for all Price List.')}
+							{{__('Discount Percentage can be applied either against a Price List or for all Price List.')}}
 						</li>
 						<li>
-							${__('To not apply Pricing Rule in a particular transaction, all applicable Pricing Rules should be disabled.')}
+							{{__('To not apply Pricing Rule in a particular transaction, all applicable Pricing Rules should be disabled.')}}
 						</li>
 					</ul>
 				</td></tr>
 				<tr><td>
 					<h4><i class="fa fa-question-sign"></i>
-						${__('How Pricing Rule is applied?')}
+						{{__('How Pricing Rule is applied?')}}
 					</h4>
 					<ol>
 						<li>
-							${__("Pricing Rule is first selected based on 'Apply On' field, which can be Item, Item Group or Brand.")}
+							{{__("Pricing Rule is first selected based on 'Apply On' field, which can be Item, Item Group or Brand.")}}
 						</li>
 						<li>
-							${__("Then Pricing Rules are filtered out based on Customer, Customer Group, Territory, Supplier, Supplier Type, Campaign, Sales Partner etc.")}
+							{{__("Then Pricing Rules are filtered out based on Customer, Customer Group, Territory, Supplier, Supplier Type, Campaign, Sales Partner etc.")}}
 						</li>
 						<li>
-							${__('Pricing Rules are further filtered based on quantity.')}
+							{{__('Pricing Rules are further filtered based on quantity.')}}
 						</li>
 						<li>
-							${__('If two or more Pricing Rules are found based on the above conditions, Priority is applied. Priority is a number between 0 to 20 while default value is zero (blank). Higher number means it will take precedence if there are multiple Pricing Rules with same conditions.')}
+							{{__('If two or more Pricing Rules are found based on the above conditions, Priority is applied. Priority is a number between 0 to 20 while default value is zero (blank). Higher number means it will take precedence if there are multiple Pricing Rules with same conditions.')}}
 						</li>
 						<li>
-							${__('Even if there are multiple Pricing Rules with highest priority, then following internal priorities are applied:')}
+							{{__('Even if there are multiple Pricing Rules with highest priority, then following internal priorities are applied:')}}
 							<ul>
 								<li>
-									${__('Item Code > Item Group > Brand')}
+									{{__('Item Code > Item Group > Brand')}}
 								</li>
 								<li>
-									${__('Customer > Customer Group > Territory')}
+									{{__('Customer > Customer Group > Territory')}}
 								</li>
 								<li>
-									${__('Supplier > Supplier Type')}
+									{{__('Supplier > Supplier Type')}}
 								</li>
 							</ul>
 						</li>
 						<li>
-							${__('If multiple Pricing Rules continue to prevail, users are asked to set Priority manually to resolve conflict.')}
+							{{__('If multiple Pricing Rules continue to prevail, users are asked to set Priority manually to resolve conflict.')}}
 						</li>
 					</ol>
 				</td></tr>
diff --git a/erpnext/accounts/doctype/pricing_rule/pricing_rule.py b/erpnext/accounts/doctype/pricing_rule/pricing_rule.py
index 149c476..55a5b0e 100644
--- a/erpnext/accounts/doctype/pricing_rule/pricing_rule.py
+++ b/erpnext/accounts/doctype/pricing_rule/pricing_rule.py
@@ -352,8 +352,14 @@
 		pricing_rule_rate = 0.0
 		if pricing_rule.currency == args.currency:
 			pricing_rule_rate = pricing_rule.rate
+
+		if pricing_rule_rate:
+			# Override already set price list rate (from item price)
+			# if pricing_rule_rate > 0
+			item_details.update({
+				"price_list_rate": pricing_rule_rate * args.get("conversion_factor", 1),
+			})
 		item_details.update({
-			"price_list_rate": pricing_rule_rate * args.get("conversion_factor", 1),
 			"discount_percentage": 0.0
 		})
 
diff --git a/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py b/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py
index 22a031c..ec0a485 100644
--- a/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py
+++ b/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py
@@ -484,6 +484,43 @@
 		frappe.delete_doc_if_exists("Pricing Rule", "_Test Pricing Rule 1")
 		frappe.delete_doc_if_exists("Pricing Rule", "_Test Pricing Rule 2")
 
+	def test_item_price_with_pricing_rule(self):
+		item = make_item("Water Flask")
+		make_item_price("Water Flask", "_Test Price List", 100)
+
+		pricing_rule_record = {
+			"doctype": "Pricing Rule",
+			"title": "_Test Water Flask Rule",
+			"apply_on": "Item Code",
+			"items": [{
+				"item_code": "Water Flask",
+			}],
+			"selling": 1,
+			"currency": "INR",
+			"rate_or_discount": "Rate",
+			"rate": 0,
+			"margin_type": "Percentage",
+			"margin_rate_or_amount": 2,
+			"company": "_Test Company"
+		}
+		rule = frappe.get_doc(pricing_rule_record)
+		rule.insert()
+
+		si = create_sales_invoice(do_not_save=True, item_code="Water Flask")
+		si.selling_price_list = "_Test Price List"
+		si.save()
+
+		# If rate in Rule is 0, give preference to Item Price if it exists
+		self.assertEqual(si.items[0].price_list_rate, 100)
+		self.assertEqual(si.items[0].margin_rate_or_amount, 2)
+		self.assertEqual(si.items[0].rate_with_margin, 102)
+		self.assertEqual(si.items[0].rate, 102)
+
+		si.delete()
+		rule.delete()
+		frappe.get_doc("Item Price", {"item_code": "Water Flask"}).delete()
+		item.delete()
+
 def make_pricing_rule(**args):
 	args = frappe._dict(args)
 
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
index fe5301d..1d41d0f 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
@@ -99,6 +99,7 @@
 					target: me.frm,
 					setters: {
 						supplier: me.frm.doc.supplier || undefined,
+						schedule_date: undefined
 					},
 					get_query_filters: {
 						docstatus: 1,
@@ -107,16 +108,16 @@
 						company: me.frm.doc.company
 					}
 				})
-			}, __("Get items from"));
+			}, __("Get Items From"));
 
 			this.frm.add_custom_button(__('Purchase Receipt'), function() {
 				erpnext.utils.map_current_doc({
 					method: "erpnext.stock.doctype.purchase_receipt.purchase_receipt.make_purchase_invoice",
 					source_doctype: "Purchase Receipt",
 					target: me.frm,
-					date_field: "posting_date",
 					setters: {
 						supplier: me.frm.doc.supplier || undefined,
+						posting_date: undefined
 					},
 					get_query_filters: {
 						docstatus: 1,
@@ -125,7 +126,7 @@
 						is_return: 0
 					}
 				})
-			}, __("Get items from"));
+			}, __("Get Items From"));
 		}
 		this.frm.toggle_reqd("supplier_warehouse", this.frm.doc.is_subcontracted==="Yes");
 
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
index 8925b87..2df77a8 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
@@ -1,5 +1,6 @@
 {
  "actions": [],
+ "allow_auto_repeat": 1,
  "allow_import": 1,
  "autoname": "naming_series:",
  "creation": "2013-05-21 16:16:39",
@@ -1334,7 +1335,8 @@
  "icon": "fa fa-file-text",
  "idx": 204,
  "is_submittable": 1,
- "modified": "2020-09-21 12:22:09.164068",
+ "links": [],
+ "modified": "2020-10-30 13:57:18.266978",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "Purchase Invoice",
@@ -1396,4 +1398,4 @@
  "timeline_field": "supplier",
  "title_field": "title",
  "track_changes": 1
-}
+}
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
index 2e5a714..f2499d2 100644
--- a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
@@ -998,7 +998,7 @@
 		'expense_account': args.expense_account or '_Test Account Cost for Goods Sold - _TC',
 		"conversion_factor": 1.0,
 		"serial_no": args.serial_no,
-		"stock_uom": "_Test UOM",
+		"stock_uom": args.uom or "_Test UOM",
 		"cost_center": args.cost_center or "_Test Cost Center - _TC",
 		"project": args.project,
 		"rejected_warehouse": args.rejected_warehouse or "",
@@ -1040,7 +1040,8 @@
 	pi.is_return = args.is_return
 	pi.credit_to = args.return_against or "Creditors - _TC"
 	pi.is_subcontracted = args.is_subcontracted or "No"
-	pi.supplier_warehouse = "_Test Warehouse 1 - _TC"
+	if args.supplier_warehouse: 
+		pi.supplier_warehouse = "_Test Warehouse 1 - _TC"
 
 	pi.append("items", {
 		"item_code": args.item or args.item_code or "_Test Item",
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
index 9af584e..502e65e 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
@@ -199,7 +199,7 @@
 						company: me.frm.doc.company
 					}
 				})
-			}, __("Get items from"));
+			}, __("Get Items From"));
 	},
 
 	quotation_btn: function() {
@@ -223,7 +223,7 @@
 						company: me.frm.doc.company
 					}
 				})
-			}, __("Get items from"));
+			}, __("Get Items From"));
 	},
 
 	delivery_note_btn: function() {
@@ -251,7 +251,7 @@
 						};
 					}
 				});
-			}, __("Get items from"));
+			}, __("Get Items From"));
 	},
 
 	tc_name: function() {
@@ -812,10 +812,10 @@
 			if (cint(frm.doc.docstatus==0) && cur_frm.page.current_view_name!=="pos" && !frm.doc.is_return) {
 				frm.add_custom_button(__('Healthcare Services'), function() {
 					get_healthcare_services_to_invoice(frm);
-				},"Get items from");
+				},"Get Items From");
 				frm.add_custom_button(__('Prescriptions'), function() {
 					get_drugs_to_invoice(frm);
-				},"Get items from");
+				},"Get Items From");
 			}
 		}
 		else {
@@ -1080,7 +1080,7 @@
 				description:'Quantity will be calculated only for items which has "Nos" as UoM. You may change as required for each invoice item.',
 				get_query: function(doc) {
 					return {
-						filters: { 
+						filters: {
 							patient: dialog.get_value("patient"),
 							company: frm.doc.company,
 							docstatus: 1
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json
index ae40153..17fbe2d 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json
@@ -1,5 +1,6 @@
 {
  "actions": [],
+ "allow_auto_repeat": 1,
  "allow_import": 1,
  "autoname": "naming_series:",
  "creation": "2013-05-24 19:29:05",
@@ -1955,7 +1956,7 @@
  "idx": 181,
  "is_submittable": 1,
  "links": [],
- "modified": "2020-10-09 15:59:57.544736",
+ "modified": "2020-10-30 13:57:45.086303",
  "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 4b59887..af6c696 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
@@ -1401,6 +1401,7 @@
 	def set_missing_values(source, target):
 		target.ignore_pricing_rule = 1
 		target.run_method("set_missing_values")
+		target.run_method("set_po_nos")
 		target.run_method("calculate_taxes_and_totals")
 
 	def update_item(source_doc, target_doc, source_parent):
diff --git a/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py b/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py
index 8b5e68b..32ad4cb 100644
--- a/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py
+++ b/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py
@@ -140,9 +140,9 @@
 		else:
 			tds_amount = _get_tds(net_total, tax_details.rate)
 	else:
-		supplier_credit_amount = frappe.get_all('Purchase Invoice Item',
-			fields = ['sum(net_amount)'],
-			filters = {'parent': ('in', vouchers), 'docstatus': 1}, as_list=1)
+		supplier_credit_amount = frappe.get_all('Purchase Invoice',
+			fields = ['sum(net_total)'],
+			filters = {'name': ('in', vouchers), 'docstatus': 1, "apply_tds": 1}, as_list=1)
 
 		supplier_credit_amount = (supplier_credit_amount[0][0]
 			if supplier_credit_amount and supplier_credit_amount[0][0] else 0)
diff --git a/erpnext/accounts/doctype/tax_withholding_category/test_tax_withholding_category.py b/erpnext/accounts/doctype/tax_withholding_category/test_tax_withholding_category.py
index b146899..ef77674 100644
--- a/erpnext/accounts/doctype/tax_withholding_category/test_tax_withholding_category.py
+++ b/erpnext/accounts/doctype/tax_withholding_category/test_tax_withholding_category.py
@@ -7,6 +7,7 @@
 import unittest
 from frappe.utils import today
 from erpnext.accounts.utils import get_fiscal_year
+from erpnext.buying.doctype.supplier.test_supplier import create_supplier
 
 test_dependencies = ["Supplier Group"]
 
@@ -101,6 +102,32 @@
 		for d in invoices:
 			d.cancel()
 
+	def test_single_threshold_tds_with_previous_vouchers_and_no_tds(self):
+		invoices = []
+		doc = create_supplier(supplier_name = "Test TDS Supplier ABC",
+			tax_withholding_category="Single Threshold TDS")
+		supplier = doc.name
+
+		pi = create_purchase_invoice(supplier=supplier)
+		pi.submit()
+		invoices.append(pi)
+
+		# TDS not applied
+		pi = create_purchase_invoice(supplier=supplier, do_not_apply_tds=True)
+		pi.submit()
+		invoices.append(pi)
+
+		pi = create_purchase_invoice(supplier=supplier)
+		pi.submit()
+		invoices.append(pi)
+
+		self.assertEqual(pi.taxes_and_charges_deducted, 2000)
+		self.assertEqual(pi.grand_total, 8000)
+
+		# delete invoices to avoid clashing
+		for d in invoices:
+			d.cancel()
+
 def create_purchase_invoice(**args):
 	# return sales invoice doc object
 	item = frappe.get_doc('Item', {'item_name': 'TDS Item'})
@@ -109,7 +136,7 @@
 	pi = frappe.get_doc({
 		"doctype": "Purchase Invoice",
 		"posting_date": today(),
-		"apply_tds": 1,
+		"apply_tds": 0 if args.do_not_apply_tds else 1,
 		"supplier": args.supplier,
 		"company": '_Test Company',
 		"taxes_and_charges": "",
diff --git a/erpnext/accounts/page/bank_reconciliation/bank_reconciliation.js b/erpnext/accounts/page/bank_reconciliation/bank_reconciliation.js
index 9703527..6ae81d7 100644
--- a/erpnext/accounts/page/bank_reconciliation/bank_reconciliation.js
+++ b/erpnext/accounts/page/bank_reconciliation/bank_reconciliation.js
@@ -156,7 +156,7 @@
 
 	setup_transactions_dom() {
 		const me = this;
-		me.parent.$main_section.append(`<div class="transactions-table"></div>`)
+		me.parent.$main_section.append('<div class="transactions-table"></div>');
 	}
 
 	create_datatable() {
@@ -167,9 +167,7 @@
 			})
 		}
 		catch(err) {
-			let msg = __(`Your file could not be processed by ERPNext.
-						<br>It should be a standard CSV or XLSX file.
-						<br>The headers should be in the first row.`)
+			let msg = __("Your file could not be processed. It should be a standard CSV or XLSX file with headers in the first row.");
 			frappe.throw(msg)
 		}
 
diff --git a/erpnext/accounts/party.py b/erpnext/accounts/party.py
index e8d3cd3..64268b8 100644
--- a/erpnext/accounts/party.py
+++ b/erpnext/accounts/party.py
@@ -59,7 +59,7 @@
 			billing_address=party_address, shipping_address=shipping_address)
 
 	if fetch_payment_terms_template:
-		party_details["payment_terms_template"] = get_pyt_term_template(party.name, party_type, company)
+		party_details["payment_terms_template"] = get_payment_terms_template(party.name, party_type, company)
 
 	if not party_details.get("currency"):
 		party_details["currency"] = currency
@@ -315,7 +315,7 @@
 	due_date = None
 	if (bill_date or posting_date) and party:
 		due_date = bill_date or posting_date
-		template_name = get_pyt_term_template(party, party_type, company)
+		template_name = get_payment_terms_template(party, party_type, company)
 
 		if template_name:
 			due_date = get_due_date_from_template(template_name, posting_date, bill_date).strftime("%Y-%m-%d")
@@ -422,7 +422,7 @@
 
 
 @frappe.whitelist()
-def get_pyt_term_template(party_name, party_type, company=None):
+def get_payment_terms_template(party_name, party_type, company=None):
 	if party_type not in ("Customer", "Supplier"):
 		return
 	template = None
diff --git a/erpnext/accounts/print_format/bank_and_cash_payment_voucher/bank_and_cash_payment_voucher.html b/erpnext/accounts/print_format/bank_and_cash_payment_voucher/bank_and_cash_payment_voucher.html
index 6fe6999..e588ed6 100644
--- a/erpnext/accounts/print_format/bank_and_cash_payment_voucher/bank_and_cash_payment_voucher.html
+++ b/erpnext/accounts/print_format/bank_and_cash_payment_voucher/bank_and_cash_payment_voucher.html
@@ -19,7 +19,7 @@
             </div>
             <div class="col-xs-6">
                 <table>
-                    <tr><td><strong>Date: </strong></td><td>{{ frappe.utils.formatdate(doc.creation) }}</td></tr>
+                    <tr><td><strong>Date: </strong></td><td>{{ frappe.utils.format_date(doc.creation) }}</td></tr>
                 </table>
             </div>
     </div>
diff --git a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py
index 044fc1d..51fc7ec 100755
--- a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py
+++ b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py
@@ -160,6 +160,8 @@
 			else:
 				# advance / unlinked payment or other adjustment
 				row.paid -= gle_balance
+		if gle.cost_center:
+			row.cost_center =  str(gle.cost_center)
 
 	def update_sub_total_row(self, row, party):
 		total_row = self.total_row_map.get(party)
@@ -210,7 +212,6 @@
 		for key, row in self.voucher_balance.items():
 			row.outstanding = flt(row.invoiced - row.paid - row.credit_note, self.currency_precision)
 			row.invoice_grand_total = row.invoiced
-
 			if abs(row.outstanding) > 1.0/10 ** self.currency_precision:
 				# non-zero oustanding, we must consider this row
 
@@ -577,7 +578,7 @@
 
 		self.gl_entries = frappe.db.sql("""
 			select
-				name, posting_date, account, party_type, party, voucher_type, voucher_no,
+				name, posting_date, account, party_type, party, voucher_type, voucher_no, cost_center,
 				against_voucher_type, against_voucher, account_currency, remarks, {0}
 			from
 				`tabGL Entry`
@@ -741,6 +742,7 @@
 			self.add_column(_("Customer Contact"), fieldname='customer_primary_contact',
 				fieldtype='Link', options='Contact')
 
+		self.add_column(label=_('Cost Center'), fieldname='cost_center', fieldtype='Data')
 		self.add_column(label=_('Voucher Type'), fieldname='voucher_type', fieldtype='Data')
 		self.add_column(label=_('Voucher No'), fieldname='voucher_no', fieldtype='Dynamic Link',
 			options='voucher_type', width=180)
diff --git a/erpnext/assets/doctype/asset/asset.js b/erpnext/assets/doctype/asset/asset.js
index 7ad164a..b2318a2 100644
--- a/erpnext/assets/doctype/asset/asset.js
+++ b/erpnext/assets/doctype/asset/asset.js
@@ -373,8 +373,8 @@
 			doctype_field = frappe.scrub(doctype)
 			frm.set_value(doctype_field, '');
 			frappe.msgprint({
-				title: __(`Invalid ${doctype}`),
-				message: __(`The selected ${doctype} doesn't contains selected Asset Item.`),
+				title: __('Invalid {0}', [__(doctype)]),
+				message: __('The selected {0} does not contain the selected Asset Item.', [__(doctype)]),
 				indicator: 'red'
 			});
 		}
@@ -436,7 +436,7 @@
 	depreciation_start_date: function(frm, cdt, cdn) {
 		const book = locals[cdt][cdn];
 		if (frm.doc.available_for_use_date && book.depreciation_start_date == frm.doc.available_for_use_date) {
-			frappe.msgprint(__(`Depreciation Posting Date should not be equal to Available for Use Date.`));
+			frappe.msgprint(__("Depreciation Posting Date should not be equal to Available for Use Date."));
 			book.depreciation_start_date = "";
 			frm.refresh_field("finance_books");
 		}
diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.js b/erpnext/buying/doctype/purchase_order/purchase_order.js
index 9f2b971..47483c9 100644
--- a/erpnext/buying/doctype/purchase_order/purchase_order.js
+++ b/erpnext/buying/doctype/purchase_order/purchase_order.js
@@ -90,6 +90,11 @@
 		this.frm.set_df_property("drop_ship", "hidden", !is_drop_ship);
 
 		if(doc.docstatus == 1) {
+			this.frm.fields_dict.items_section.wrapper.addClass("hide-border");
+			if(!this.frm.doc.set_warehouse) {
+				this.frm.fields_dict.items_section.wrapper.removeClass("hide-border");
+			}
+
 			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'), () => {
@@ -126,16 +131,25 @@
 			if(doc.status != "Closed") {
 				if (doc.status != "On Hold") {
 					if(flt(doc.per_received) < 100 && allow_receipt) {
-						cur_frm.add_custom_button(__('Receipt'), this.make_purchase_receipt, __('Create'));
+						cur_frm.add_custom_button(__('Purchase 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) < 100)
-						cur_frm.add_custom_button(__('Invoice'),
+						cur_frm.add_custom_button(__('Purchase Invoice'),
 							this.make_purchase_invoice, __('Create'));
 
+					if(flt(doc.per_billed)==0 && doc.status != "Delivered") {
+						cur_frm.add_custom_button(__('Payment'), cur_frm.cscript.make_payment_entry, __('Create'));
+					}
+
+					if(flt(doc.per_billed)==0) {
+						this.frm.add_custom_button(__('Payment Request'),
+							function() { me.make_payment_request() }, __('Create'));
+					}
+
 					if(!doc.auto_repeat) {
 						cur_frm.add_custom_button(__('Subscription'), function() {
 							erpnext.utils.make_subscription(doc.doctype, doc.name)
@@ -156,13 +170,7 @@
 						});
 					}
 				}
-				if(flt(doc.per_billed)==0) {
-					this.frm.add_custom_button(__('Payment Request'),
-						function() { me.make_payment_request() }, __('Create'));
-				}
-				if(flt(doc.per_billed)==0 && doc.status != "Delivered") {
-					cur_frm.add_custom_button(__('Payment'), cur_frm.cscript.make_payment_entry, __('Create'));
-				}
+
 				cur_frm.page.set_inner_btn_group_as_primary(__('Create'));
 			}
 		} else if(doc.docstatus===0) {
@@ -299,7 +307,7 @@
 			if(me.values) {
 				me.values.sub_con_rm_items.map((row,i) => {
 					if (!row.item_code || !row.rm_item_code || !row.warehouse || !row.qty || row.qty === 0) {
-						frappe.throw(__("Item Code, warehouse, quantity are required on row" + (i+1)));
+						frappe.throw(__("Item Code, warehouse, quantity are required on row {0}", [i+1]));
 					}
 				})
 				me._make_rm_stock_entry(me.dialog.fields_dict.sub_con_rm_items.grid.get_selected_children())
@@ -358,15 +366,19 @@
 					method: "erpnext.stock.doctype.material_request.material_request.make_purchase_order",
 					source_doctype: "Material Request",
 					target: me.frm,
-					setters: {},
+					setters: {
+						schedule_date: undefined,
+						status: undefined
+					},
 					get_query_filters: {
 						material_request_type: "Purchase",
 						docstatus: 1,
 						status: ["!=", "Stopped"],
 						per_ordered: ["<", 99.99],
+						company: me.frm.doc.company
 					}
 				})
-			}, __("Get items from"));
+			}, __("Get Items From"));
 
 		this.frm.add_custom_button(__('Supplier Quotation'),
 			function() {
@@ -375,16 +387,17 @@
 					source_doctype: "Supplier Quotation",
 					target: me.frm,
 					setters: {
-						supplier: me.frm.doc.supplier
+						supplier: me.frm.doc.supplier,
+						valid_till: undefined
 					},
 					get_query_filters: {
 						docstatus: 1,
-						status: ["!=", "Stopped"],
+						status: ["not in", ["Stopped", "Expired"]],
 					}
 				})
-			}, __("Get items from"));
+			}, __("Get Items From"));
 
-		this.frm.add_custom_button(__('Update rate as per last purchase'),
+		this.frm.add_custom_button(__('Update Rate as per Last Purchase'),
 			function() {
 				frappe.call({
 					"method": "get_last_purchase_rate",
diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.json b/erpnext/buying/doctype/purchase_order/purchase_order.json
index 2747c7c..71231f6 100644
--- a/erpnext/buying/doctype/purchase_order/purchase_order.json
+++ b/erpnext/buying/doctype/purchase_order/purchase_order.json
@@ -1,5 +1,6 @@
 {
  "actions": [],
+ "allow_auto_repeat": 1,
  "allow_import": 1,
  "autoname": "naming_series:",
  "creation": "2013-05-21 16:16:39",
@@ -30,8 +31,8 @@
   "customer_contact_email",
   "section_addresses",
   "supplier_address",
-  "contact_person",
   "address_display",
+  "contact_person",
   "contact_display",
   "contact_mobile",
   "contact_email",
@@ -49,12 +50,14 @@
   "plc_conversion_rate",
   "ignore_pricing_rule",
   "sec_warehouse",
-  "set_warehouse",
-  "col_break_warehouse",
   "is_subcontracted",
+  "col_break_warehouse",
   "supplier_warehouse",
-  "items_section",
+  "before_items_section",
   "scan_barcode",
+  "items_col_break",
+  "set_warehouse",
+  "items_section",
   "items",
   "sb_last_purchase",
   "total_qty",
@@ -108,18 +111,13 @@
   "payment_terms_template",
   "payment_schedule",
   "tracking_section",
-  "per_billed",
+  "status",
   "column_break_75",
+  "per_billed",
   "per_received",
   "terms_section_break",
   "tc_name",
   "terms",
-  "more_info",
-  "status",
-  "ref_sq",
-  "column_break_74",
-  "party_account_currency",
-  "inter_company_order_reference",
   "column_break5",
   "letter_head",
   "select_print_heading",
@@ -131,7 +129,12 @@
   "to_date",
   "column_break_97",
   "auto_repeat",
-  "update_auto_repeat_reference"
+  "update_auto_repeat_reference",
+  "more_info",
+  "ref_sq",
+  "column_break_74",
+  "party_account_currency",
+  "inter_company_order_reference"
  ],
  "fields": [
   {
@@ -313,34 +316,34 @@
   {
    "fieldname": "supplier_address",
    "fieldtype": "Link",
-   "label": "Select Supplier Address",
+   "label": "Supplier Address",
    "options": "Address",
    "print_hide": 1
   },
   {
    "fieldname": "contact_person",
    "fieldtype": "Link",
-   "label": "Contact Person",
+   "label": "Supplier Contact",
    "options": "Contact",
    "print_hide": 1
   },
   {
    "fieldname": "address_display",
    "fieldtype": "Small Text",
-   "label": "Address",
+   "label": "Supplier Address Details",
    "read_only": 1
   },
   {
    "fieldname": "contact_display",
    "fieldtype": "Small Text",
    "in_global_search": 1,
-   "label": "Contact",
+   "label": "Contact Name",
    "read_only": 1
   },
   {
    "fieldname": "contact_mobile",
    "fieldtype": "Small Text",
-   "label": "Mobile No",
+   "label": "Contact Mobile No",
    "read_only": 1
   },
   {
@@ -358,14 +361,14 @@
   {
    "fieldname": "shipping_address",
    "fieldtype": "Link",
-   "label": "Select Shipping Address",
+   "label": "Company Shipping Address",
    "options": "Address",
    "print_hide": 1
   },
   {
    "fieldname": "shipping_address_display",
    "fieldtype": "Small Text",
-   "label": "Shipping Address",
+   "label": "Shipping Address Details",
    "print_hide": 1,
    "read_only": 1
   },
@@ -433,7 +436,8 @@
   },
   {
    "fieldname": "sec_warehouse",
-   "fieldtype": "Section Break"
+   "fieldtype": "Section Break",
+   "label": "Subcontracting"
   },
   {
    "description": "Sets 'Warehouse' in each row of the Items table.",
@@ -466,6 +470,7 @@
   {
    "fieldname": "items_section",
    "fieldtype": "Section Break",
+   "hide_border": 1,
    "oldfieldtype": "Section Break",
    "options": "fa fa-shopping-cart"
   },
@@ -598,7 +603,8 @@
   },
   {
    "fieldname": "section_break_52",
-   "fieldtype": "Section Break"
+   "fieldtype": "Section Break",
+   "hide_border": 1
   },
   {
    "fieldname": "taxes",
@@ -626,10 +632,12 @@
   {
    "fieldname": "totals",
    "fieldtype": "Section Break",
+   "label": "Taxes and Charges",
    "oldfieldtype": "Section Break",
    "options": "fa fa-money"
   },
   {
+   "depends_on": "base_taxes_and_charges_added",
    "fieldname": "base_taxes_and_charges_added",
    "fieldtype": "Currency",
    "label": "Taxes and Charges Added (Company Currency)",
@@ -640,6 +648,7 @@
    "read_only": 1
   },
   {
+   "depends_on": "base_taxes_and_charges_deducted",
    "fieldname": "base_taxes_and_charges_deducted",
    "fieldtype": "Currency",
    "label": "Taxes and Charges Deducted (Company Currency)",
@@ -650,6 +659,7 @@
    "read_only": 1
   },
   {
+   "depends_on": "base_total_taxes_and_charges",
    "fieldname": "base_total_taxes_and_charges",
    "fieldtype": "Currency",
    "label": "Total Taxes and Charges (Company Currency)",
@@ -665,6 +675,7 @@
    "fieldtype": "Column Break"
   },
   {
+   "depends_on": "taxes_and_charges_added",
    "fieldname": "taxes_and_charges_added",
    "fieldtype": "Currency",
    "label": "Taxes and Charges Added",
@@ -675,6 +686,7 @@
    "read_only": 1
   },
   {
+   "depends_on": "taxes_and_charges_deducted",
    "fieldname": "taxes_and_charges_deducted",
    "fieldtype": "Currency",
    "label": "Taxes and Charges Deducted",
@@ -685,6 +697,7 @@
    "read_only": 1
   },
   {
+   "depends_on": "total_taxes_and_charges",
    "fieldname": "total_taxes_and_charges",
    "fieldtype": "Currency",
    "label": "Total Taxes and Charges",
@@ -694,7 +707,7 @@
   },
   {
    "collapsible": 1,
-   "collapsible_depends_on": "discount_amount",
+   "collapsible_depends_on": "apply_discount_on",
    "fieldname": "discount_section",
    "fieldtype": "Section Break",
    "label": "Additional Discount"
@@ -734,7 +747,8 @@
   },
   {
    "fieldname": "totals_section",
-   "fieldtype": "Section Break"
+   "fieldtype": "Section Break",
+   "label": "Totals"
   },
   {
    "fieldname": "base_grand_total",
@@ -902,12 +916,12 @@
   },
   {
    "fieldname": "ref_sq",
-   "fieldtype": "Data",
-   "hidden": 1,
-   "label": "Ref SQ",
+   "fieldtype": "Link",
+   "label": "Supplier Quotation",
    "no_copy": 1,
    "oldfieldname": "ref_sq",
    "oldfieldtype": "Data",
+   "options": "Supplier Quotation",
    "print_hide": 1,
    "read_only": 1
   },
@@ -1061,7 +1075,7 @@
    "collapsible": 1,
    "fieldname": "tracking_section",
    "fieldtype": "Section Break",
-   "label": "Tracking"
+   "label": "Order Status"
   },
   {
    "fieldname": "column_break_75",
@@ -1070,21 +1084,29 @@
   {
    "fieldname": "billing_address",
    "fieldtype": "Link",
-   "label": "Select Billing Address",
+   "label": "Company Billing Address",
    "options": "Address"
   },
   {
    "fieldname": "billing_address_display",
    "fieldtype": "Small Text",
-   "label": "Billing Address",
+   "label": "Billing Address Details",
    "read_only": 1
+  },
+  {
+   "fieldname": "before_items_section",
+   "fieldtype": "Section Break"
+  },
+  {
+   "fieldname": "items_col_break",
+   "fieldtype": "Column Break"
   }
  ],
  "icon": "fa fa-file-text",
  "idx": 105,
  "is_submittable": 1,
  "links": [],
- "modified": "2020-10-07 14:31:57.661221",
+ "modified": "2020-10-30 13:58:14.697921",
  "modified_by": "Administrator",
  "module": "Buying",
  "name": "Purchase Order",
diff --git a/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json b/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json
index 7a52c28..10db240 100644
--- a/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json
+++ b/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json
@@ -24,6 +24,7 @@
   "col_break2",
   "uom",
   "conversion_factor",
+  "stock_qty",
   "sec_break1",
   "price_list_rate",
   "discount_percentage",
@@ -46,11 +47,8 @@
   "column_break_32",
   "base_net_rate",
   "base_net_amount",
-  "billed_amt",
   "warehouse_and_reference",
   "warehouse",
-  "delivered_by_supplier",
-  "project",
   "material_request",
   "material_request_item",
   "sales_order",
@@ -58,36 +56,37 @@
   "supplier_quotation",
   "supplier_quotation_item",
   "col_break5",
+  "delivered_by_supplier",
   "against_blanket_order",
   "blanket_order",
   "blanket_order_rate",
   "item_group",
   "brand",
-  "bom",
-  "include_exploded_items",
   "section_break_56",
-  "stock_qty",
-  "column_break_60",
   "received_qty",
   "returned_qty",
-  "manufacture_details",
-  "manufacturer",
-  "column_break_14",
-  "manufacturer_part_no",
-  "more_info_section_break",
-  "is_fixed_asset",
-  "item_tax_rate",
+  "column_break_60",
+  "billed_amt",
   "accounting_details",
   "expense_account",
-  "column_break_68",
+  "manufacture_details",
+  "manufacturer",
+  "manufacturer_part_no",
+  "column_break_14",
+  "bom",
+  "include_exploded_items",
   "item_weight_details",
   "weight_per_unit",
   "total_weight",
   "column_break_40",
   "weight_uom",
   "accounting_dimensions_section",
-  "cost_center",
+  "project",
   "dimension_col_break",
+  "cost_center",
+  "more_info_section_break",
+  "is_fixed_asset",
+  "item_tax_rate",
   "section_break_72",
   "page_break"
  ],
@@ -346,6 +345,7 @@
   },
   {
    "default": "0",
+   "depends_on": "is_free_item",
    "fieldname": "is_free_item",
    "fieldtype": "Check",
    "label": "Is Free Item",
@@ -508,9 +508,10 @@
   },
   {
    "default": "0",
+   "depends_on": "delivered_by_supplier",
    "fieldname": "delivered_by_supplier",
    "fieldtype": "Check",
-   "label": "To be delivered to customer",
+   "label": "To be Delivered to Customer",
    "print_hide": 1,
    "read_only": 1
   },
@@ -558,6 +559,7 @@
    "read_only": 1
   },
   {
+   "depends_on": "eval:parent.is_subcontracted == 'Yes'",
    "fieldname": "bom",
    "fieldtype": "Link",
    "label": "BOM",
@@ -574,21 +576,21 @@
   },
   {
    "fieldname": "section_break_56",
-   "fieldtype": "Section Break"
+   "fieldtype": "Section Break",
+   "label": "Billed, Received & Returned"
   },
   {
    "fieldname": "stock_qty",
    "fieldtype": "Float",
-   "label": "Qty as per Stock UOM",
+   "label": "Qty in Stock UOM",
    "no_copy": 1,
-   "oldfieldname": "stock_qty",
-   "oldfieldtype": "Currency",
    "print_hide": 1,
    "print_width": "100px",
    "read_only": 1,
    "width": "100px"
   },
   {
+   "depends_on": "received_qty",
    "fieldname": "received_qty",
    "fieldtype": "Float",
    "label": "Received Qty",
@@ -612,9 +614,10 @@
    "fieldtype": "Column Break"
   },
   {
+   "depends_on": "billed_amt",
    "fieldname": "billed_amt",
    "fieldtype": "Currency",
-   "label": "Billed Amt",
+   "label": "Billed Amount",
    "no_copy": 1,
    "options": "currency",
    "print_hide": 1,
@@ -633,6 +636,7 @@
    "report_hide": 1
   },
   {
+   "collapsible": 1,
    "fieldname": "accounting_details",
    "fieldtype": "Section Break",
    "label": "Accounting Details"
@@ -645,10 +649,6 @@
    "print_hide": 1
   },
   {
-   "fieldname": "column_break_68",
-   "fieldtype": "Column Break"
-  },
-  {
    "fieldname": "cost_center",
    "fieldtype": "Link",
    "label": "Cost Center",
@@ -715,6 +715,7 @@
   },
   {
    "default": "0",
+   "depends_on": "is_fixed_asset",
    "fetch_from": "item_code.is_fixed_asset",
    "fieldname": "is_fixed_asset",
    "fieldtype": "Check",
@@ -728,9 +729,10 @@
   }
  ],
  "idx": 1,
+ "index_web_pages_for_search": 1,
  "istable": 1,
  "links": [],
- "modified": "2020-04-21 11:55:58.643393",
+ "modified": "2020-10-30 11:59:47.670951",
  "modified_by": "Administrator",
  "module": "Buying",
  "name": "Purchase Order Item",
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 cf30e30..c427242 100644
--- a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.js
+++ b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.js
@@ -217,13 +217,15 @@
 						source_doctype: "Material Request",
 						target: me.frm,
 						setters: {
-							company: me.frm.doc.company
+							schedule_date: undefined,
+							status: undefined
 						},
 						get_query_filters: {
 							material_request_type: "Purchase",
 							docstatus: 1,
 							status: ["!=", "Stopped"],
-							per_ordered: ["<", 99.99]
+							per_ordered: ["<", 99.99],
+							company: me.frm.doc.company
 						}
 					})
 				}, __("Get Items From"));
@@ -236,32 +238,40 @@
 						source_doctype: "Opportunity",
 						target: me.frm,
 						setters: {
-							company: me.frm.doc.company
+							party_name: undefined,
+							opportunity_from: undefined,
+							status: undefined
 						},
+						get_query_filters: {
+							status: ["not in", ["Closed", "Lost"]],
+							company: me.frm.doc.company
+						}
 					})
 				}, __("Get Items From"));
 
 			// Get items from open Material Requests based on supplier
 			this.frm.add_custom_button(__('Possible Supplier'), function() {
 				// Create a dialog window for the user to pick their supplier
-				var d = new frappe.ui.Dialog({
+				var dialog = new frappe.ui.Dialog({
 					title: __('Select Possible Supplier'),
 					fields: [
-					{fieldname: 'supplier', fieldtype:'Link', options:'Supplier', label:'Supplier', reqd:1},
-					{fieldname: 'ok_button', fieldtype:'Button', label:'Get Items from Material Requests'},
-					]
-				});
-
-				// On the user clicking the ok button
-				d.fields_dict.ok_button.input.onclick = function() {
-					var btn = d.fields_dict.ok_button.input;
-					var v = d.get_values();
-					if(v) {
-						$(btn).set_working();
+						{
+							fieldname: 'supplier',
+							fieldtype:'Link',
+							options:'Supplier',
+							label:'Supplier',
+							reqd:1,
+							description: __("Get Items from Material Requests against this Supplier")
+						}
+					],
+					primary_action_label: __("Get Items"),
+					primary_action: (args) => {
+						if(!args) return;
+						dialog.hide();
 
 						erpnext.utils.map_current_doc({
 							method: "erpnext.buying.doctype.request_for_quotation.request_for_quotation.get_item_from_material_requests_based_on_supplier",
-							source_name: v.supplier,
+							source_name: args.supplier,
 							target: me.frm,
 							setters: {
 								company: me.frm.doc.company
@@ -273,11 +283,11 @@
 								per_ordered: ["<", 99.99]
 							}
 						});
-						$(btn).done_working();
-						d.hide();
+						dialog.hide();
 					}
-				}
-				d.show();
+				});
+
+				dialog.show();
 			}, __("Get Items From"));
 
 			// Get Suppliers
diff --git a/erpnext/buying/doctype/supplier/test_supplier.py b/erpnext/buying/doctype/supplier/test_supplier.py
index a377ec9..f9c8d35 100644
--- a/erpnext/buying/doctype/supplier/test_supplier.py
+++ b/erpnext/buying/doctype/supplier/test_supplier.py
@@ -120,3 +120,20 @@
 
         # Rollback
         address.delete()
+
+def create_supplier(**args):
+    args = frappe._dict(args)
+
+    try:
+        doc = frappe.get_doc({
+            "doctype": "Supplier",
+            "supplier_name": args.supplier_name,
+            "supplier_group": args.supplier_group or "Services",
+            "supplier_type": args.supplier_type or "Company",
+            "tax_withholding_category": args.tax_withholding_category
+        }).insert()
+
+        return doc
+
+    except frappe.DuplicateEntryError:
+        return frappe.get_doc("Supplier", args.supplier_name)
\ No newline at end of file
diff --git a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.js b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.js
index 3376e82..a7cab50 100644
--- a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.js
+++ b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.js
@@ -37,16 +37,18 @@
 						source_doctype: "Material Request",
 						target: me.frm,
 						setters: {
-							company: me.frm.doc.company
+							schedule_date: undefined,
+							status: undefined
 						},
 						get_query_filters: {
 							material_request_type: "Purchase",
 							docstatus: 1,
 							status: ["!=", "Stopped"],
-							per_ordered: ["<", 99.99]
+							per_ordered: ["<", 99.99],
+							company: me.frm.doc.company
 						}
 					})
-				}, __("Get items from"));
+				}, __("Get Items From"));
 
 			this.frm.add_custom_button(__("Request for Quotation"),
 			function() {
@@ -58,16 +60,16 @@
 					source_doctype: "Request for Quotation",
 					target: me.frm,
 					setters: {
-						company: me.frm.doc.company,
 						transaction_date: null
 					},
 					get_query_filters: {
-						supplier: me.frm.doc.supplier
+						supplier: me.frm.doc.supplier,
+						company: me.frm.doc.company
 					},
 					get_query_method: "erpnext.buying.doctype.request_for_quotation.request_for_quotation.get_rfq_containing_supplier"
 
 				})
-			}, __("Get items from"));
+			}, __("Get Items From"));
 		}
 	},
 
diff --git a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.json b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.json
index 9a092ca..b39c989 100644
--- a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.json
+++ b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.json
@@ -1,5 +1,6 @@
 {
  "actions": [],
+ "allow_auto_repeat": 1,
  "allow_import": 1,
  "autoname": "naming_series:",
  "creation": "2013-05-21 16:16:45",
@@ -807,7 +808,7 @@
  "idx": 29,
  "is_submittable": 1,
  "links": [],
- "modified": "2020-10-01 20:56:17.932007",
+ "modified": "2020-10-30 13:58:33.043971",
  "modified_by": "Administrator",
  "module": "Buying",
  "name": "Supplier Quotation",
diff --git a/erpnext/communication/doctype/communication_medium/communication_medium.json b/erpnext/communication/doctype/communication_medium/communication_medium.json
index f009b38..1e1fe3b 100644
--- a/erpnext/communication/doctype/communication_medium/communication_medium.json
+++ b/erpnext/communication/doctype/communication_medium/communication_medium.json
@@ -1,12 +1,14 @@
 {
+ "actions": [],
  "autoname": "Prompt",
  "creation": "2019-06-05 11:48:30.572795",
  "doctype": "DocType",
  "engine": "InnoDB",
  "field_order": [
+  "communication_channel",
   "communication_medium_type",
-  "catch_all",
   "column_break_3",
+  "catch_all",
   "provider",
   "disabled",
   "timeslots_section",
@@ -54,9 +56,16 @@
    "fieldtype": "Table",
    "label": "Timeslots",
    "options": "Communication Medium Timeslot"
+  },
+  {
+   "fieldname": "communication_channel",
+   "fieldtype": "Select",
+   "label": "Communication Channel",
+   "options": "\nExotel"
   }
  ],
- "modified": "2019-06-05 11:49:30.769006",
+ "links": [],
+ "modified": "2020-10-27 16:22:08.068542",
  "modified_by": "Administrator",
  "module": "Communication",
  "name": "Communication Medium",
diff --git a/erpnext/controllers/selling_controller.py b/erpnext/controllers/selling_controller.py
index 5886171..515239a 100644
--- a/erpnext/controllers/selling_controller.py
+++ b/erpnext/controllers/selling_controller.py
@@ -371,13 +371,27 @@
 		self.make_sl_entries(sl_entries)
 
 	def set_po_nos(self):
-		if self.doctype in ("Delivery Note", "Sales Invoice") and hasattr(self, "items"):
-			ref_fieldname = "against_sales_order" if self.doctype == "Delivery Note" else "sales_order"
-			sales_orders = list(set([d.get(ref_fieldname) for d in self.items if d.get(ref_fieldname)]))
-			if sales_orders:
-				po_nos = frappe.get_all('Sales Order', 'po_no', filters = {'name': ('in', sales_orders)})
-				if po_nos and po_nos[0].get('po_no'):
-					self.po_no = ', '.join(list(set([d.po_no for d in po_nos if d.po_no])))
+		if self.doctype == 'Sales Invoice' and hasattr(self, "items"):
+			self.set_pos_for_sales_invoice()
+		if self.doctype == 'Delivery Note' and hasattr(self, "items"):
+			self.set_pos_for_delivery_note()
+
+	def set_pos_for_sales_invoice(self):
+		po_nos = []
+		self.get_po_nos('Sales Order', 'sales_order', po_nos)
+		self.get_po_nos('Delivery Note', 'delivery_note', po_nos)
+		self.po_no = ', '.join(list(set(x.strip() for x in ','.join(po_nos).split(','))))
+
+	def set_pos_for_delivery_note(self):
+		po_nos = []
+		self.get_po_nos('Sales Order', 'against_sales_order', po_nos)
+		self.get_po_nos('Sales Invoice', 'against_sales_invoice', po_nos)
+		self.po_no = ', '.join(list(set(x.strip() for x in ','.join(po_nos).split(','))))
+
+	def get_po_nos(self, ref_doctype, ref_fieldname, po_nos):
+		doc_list = list(set([d.get(ref_fieldname) for d in self.items if d.get(ref_fieldname)]))
+		if doc_list:
+			po_nos += [d.po_no for d in frappe.get_all(ref_doctype, 'po_no', filters = {'name': ('in', doc_list)}) if d.get('po_no')]
 
 	def set_gross_profit(self):
 		if self.doctype in ["Sales Order", "Quotation"]:
@@ -402,26 +416,26 @@
 			return
 
 		for d in self.get('items'):
-			if self.doctype == "Sales Invoice":
-				e = [d.item_code, d.description, d.warehouse, d.sales_order or d.delivery_note, d.batch_no or '']
-				f = [d.item_code, d.description, d.sales_order or d.delivery_note]
+			if self.doctype in ["POS Invoice","Sales Invoice"]:
+				stock_items = [d.item_code, d.description, d.warehouse, d.sales_order or d.delivery_note, d.batch_no or '']
+				non_stock_items = [d.item_code, d.description, d.sales_order or d.delivery_note]
 			elif self.doctype == "Delivery Note":
-				e = [d.item_code, d.description, d.warehouse, d.against_sales_order or d.against_sales_invoice, d.batch_no or '']
-				f = [d.item_code, d.description, d.against_sales_order or d.against_sales_invoice]
+				stock_items = [d.item_code, d.description, d.warehouse, d.against_sales_order or d.against_sales_invoice, d.batch_no or '']
+				non_stock_items = [d.item_code, d.description, d.against_sales_order or d.against_sales_invoice]
 			elif self.doctype in ["Sales Order", "Quotation"]:
-				e = [d.item_code, d.description, d.warehouse, '']
-				f = [d.item_code, d.description]
+				stock_items = [d.item_code, d.description, d.warehouse, '']
+				non_stock_items = [d.item_code, d.description]
 
 			if frappe.db.get_value("Item", d.item_code, "is_stock_item") == 1:
-				if e in check_list:
+				if stock_items in check_list:
 					frappe.throw(_("Note: Item {0} entered multiple times").format(d.item_code))
 				else:
-					check_list.append(e)
+					check_list.append(stock_items)
 			else:
-				if f in chk_dupl_itm:
+				if non_stock_items in chk_dupl_itm:
 					frappe.throw(_("Note: Item {0} entered multiple times").format(d.item_code))
 				else:
-					chk_dupl_itm.append(f)
+					chk_dupl_itm.append(non_stock_items)
 
 	def validate_target_warehouse(self):
 		items = self.get("items") + (self.get("packed_items") or [])
diff --git a/erpnext/controllers/stock_controller.py b/erpnext/controllers/stock_controller.py
index f743d70..2d2fff8 100644
--- a/erpnext/controllers/stock_controller.py
+++ b/erpnext/controllers/stock_controller.py
@@ -229,9 +229,9 @@
 
 	def check_expense_account(self, item):
 		if not item.get("expense_account"):
-			frappe.throw(_("Row #{0}: Expense Account not set for Item {1}. Please set an Expense \
-				Account in the Items table").format(item.idx, frappe.bold(item.item_code)),
-				title=_("Expense Account Missing"))
+			msg = _("Please set an Expense Account in the Items table")
+			frappe.throw(_("Row #{0}: Expense Account not set for the Item {1}. {2}")
+				.format(item.idx, frappe.bold(item.item_code), msg), title=_("Expense Account Missing"))
 
 		else:
 			is_expense_account = frappe.db.get_value("Account",
@@ -247,7 +247,9 @@
 		for d in self.items:
 			if not d.batch_no: continue
 
-			serial_nos = [sr.name for sr in frappe.get_all("Serial No", {'batch_no': d.batch_no})]
+			serial_nos = [sr.name for sr in frappe.get_all("Serial No",
+				{'batch_no': d.batch_no, 'status': 'Inactive'})]
+
 			if serial_nos:
 				frappe.db.set_value("Serial No", { 'name': ['in', serial_nos] }, "batch_no", None)
 
diff --git a/erpnext/crm/doctype/appointment_booking_settings/appointment_booking_settings.js b/erpnext/crm/doctype/appointment_booking_settings/appointment_booking_settings.js
index 99b8214..dc3ae8b 100644
--- a/erpnext/crm/doctype/appointment_booking_settings/appointment_booking_settings.js
+++ b/erpnext/crm/doctype/appointment_booking_settings/appointment_booking_settings.js
@@ -4,7 +4,7 @@
 		let from_time = Date.parse('01/01/2019 ' + d.from_time);
 		let to_time = Date.parse('01/01/2019 ' + d.to_time);
 		if (from_time > to_time) {
-			frappe.throw(__(`In row ${i + 1} of Appointment Booking Slots : "To Time" must be later than "From Time"`));
+			frappe.throw(__('In row {0} of Appointment Booking Slots: "To Time" must be later than "From Time".', [i + 1]));
 		}
 	});
 }
\ No newline at end of file
diff --git a/erpnext/crm/doctype/contract_template/contract_template.json b/erpnext/crm/doctype/contract_template/contract_template.json
index ef9974f..5e4582f 100644
--- a/erpnext/crm/doctype/contract_template/contract_template.json
+++ b/erpnext/crm/doctype/contract_template/contract_template.json
@@ -23,8 +23,7 @@
   {
    "fieldname": "contract_terms",
    "fieldtype": "Text Editor",
-   "label": "Contract Terms and Conditions",
-   "read_only": 1
+   "label": "Contract Terms and Conditions"
   },
   {
    "fieldname": "sb_fulfilment",
@@ -45,7 +44,7 @@
   }
  ],
  "links": [],
- "modified": "2020-06-03 00:24:58.179816",
+ "modified": "2020-11-11 17:49:44.879363",
  "modified_by": "Administrator",
  "module": "CRM",
  "name": "Contract Template",
diff --git a/erpnext/demo/data/asset.json b/erpnext/demo/data/asset.json
index 23029ca..44db2ae 100644
--- a/erpnext/demo/data/asset.json
+++ b/erpnext/demo/data/asset.json
@@ -4,48 +4,55 @@
 		"item_code": "Computer",
 		"gross_purchase_amount": 100000,
 		"asset_owner": "Company",
-		"available_for_use_date": "2017-01-02"
+		"available_for_use_date": "2017-01-02",
+		"location": "Main Location"
 	},
 	{
 		"asset_name": "Macbook Air - 1",
 		"item_code": "Computer",
 		"gross_purchase_amount": 60000,
 		"asset_owner": "Company",
-		"available_for_use_date": "2017-10-02"
+		"available_for_use_date": "2017-10-02",
+		"location": "Avg Location"
 	},
 	{
 		"asset_name": "Conferrence Table",
 		"item_code": "Table",
 		"gross_purchase_amount": 30000,
 		"asset_owner": "Company",
-		"available_for_use_date": "2018-10-02"
+		"available_for_use_date": "2018-10-02",
+		"location": "Zany Location"
 	},
 	{
 		"asset_name": "Lunch Table",
 		"item_code": "Table",
 		"gross_purchase_amount": 20000,
 		"asset_owner": "Company",
-		"available_for_use_date": "2018-06-02"
+		"available_for_use_date": "2018-06-02",
+		"location": "Fletcher Location"
 	},
 	{
 		"asset_name": "ERPNext",
 		"item_code": "ERP",
 		"gross_purchase_amount": 100000,
 		"asset_owner": "Company",
-		"available_for_use_date": "2018-09-02"
+		"available_for_use_date": "2018-09-02",
+		"location":"Main Location"
 	},
 	{
 		"asset_name": "Chair 1",
 		"item_code": "Chair",
 		"gross_purchase_amount": 10000,
 		"asset_owner": "Company",
-		"available_for_use_date": "2018-07-02"
+		"available_for_use_date": "2018-07-02",
+		"location": "Zany Location"
 	},
 	{
 		"asset_name": "Chair 2",
 		"item_code": "Chair",
 		"gross_purchase_amount": 10000,
 		"asset_owner": "Company",
-		"available_for_use_date": "2018-07-02"
+		"available_for_use_date": "2018-07-02",
+		"location": "Avg Location"
 	}
 ]
diff --git a/erpnext/demo/data/location.json b/erpnext/demo/data/location.json
new file mode 100644
index 0000000..b521aa0
--- /dev/null
+++ b/erpnext/demo/data/location.json
@@ -0,0 +1,22 @@
+[
+    {
+        "location_name": "Main Location",
+        "latitude": 40.0,
+        "longitude": 20.0
+    },
+    {
+        "location_name": "Avg Location",
+        "latitude": 63.0,
+        "longitude": 99.3
+    },
+    {
+        "location_name": "Zany Location",
+        "latitude": 47.5,
+        "longitude": 10.0
+    },
+    {
+        "location_name": "Fletcher Location",
+        "latitude": 100.90,
+        "longitude": 80
+    }
+]
\ No newline at end of file
diff --git a/erpnext/demo/setup/manufacture.py b/erpnext/demo/setup/manufacture.py
index d384636..7d6b501 100644
--- a/erpnext/demo/setup/manufacture.py
+++ b/erpnext/demo/setup/manufacture.py
@@ -9,6 +9,7 @@
 from six import iteritems
 
 def setup_data():
+	import_json("Location")
 	import_json("Asset Category")
 	setup_item()
 	setup_workstation()
diff --git a/erpnext/demo/user/stock.py b/erpnext/demo/user/stock.py
index f95a6b8..d44da7d 100644
--- a/erpnext/demo/user/stock.py
+++ b/erpnext/demo/user/stock.py
@@ -79,7 +79,7 @@
 				if item.qty:
 					item.qty = item.qty - round(random.randint(1, item.qty))
 			try:
-				stock_reco.insert(ignore_permissions=True)
+				stock_reco.insert(ignore_permissions=True, ignore_mandatory=True)
 				stock_reco.submit()
 				frappe.db.commit()
 			except OpeningEntryAccountError:
diff --git a/erpnext/education/doctype/student_attendance/student_attendance.py b/erpnext/education/doctype/student_attendance/student_attendance.py
index 72a8f55..2e9e6cf 100644
--- a/erpnext/education/doctype/student_attendance/student_attendance.py
+++ b/erpnext/education/doctype/student_attendance/student_attendance.py
@@ -6,8 +6,10 @@
 import frappe
 from frappe.model.document import Document
 from frappe import _
-from frappe.utils import get_link_to_form, getdate
+from frappe.utils import get_link_to_form, getdate, formatdate
+from erpnext import get_default_company
 from erpnext.education.api import get_student_group_students
+from erpnext.hr.doctype.holiday_list.holiday_list import is_holiday
 
 class StudentAttendance(Document):
 	def validate(self):
@@ -17,6 +19,7 @@
 		self.set_student_group()
 		self.validate_student()
 		self.validate_duplication()
+		self.validate_is_holiday()
 
 	def set_date(self):
 		if self.course_schedule:
@@ -78,3 +81,18 @@
 			record = get_link_to_form('Student Attendance', attendance_record)
 			frappe.throw(_('Student Attendance record {0} already exists against the Student {1}')
 				.format(record, frappe.bold(self.student)), title=_('Duplicate Entry'))
+
+	def validate_is_holiday(self):
+		holiday_list = get_holiday_list()
+		if is_holiday(holiday_list, self.date):
+			frappe.throw(_('Attendance cannot be marked for {0} as it is a holiday.').format(
+				frappe.bold(formatdate(self.date))))
+
+def get_holiday_list(company=None):
+	if not company:
+		company = get_default_company() or frappe.get_all('Company')[0].name
+
+	holiday_list = frappe.get_cached_value('Company', company,  'default_holiday_list')
+	if not holiday_list:
+		frappe.throw(_('Please set a default Holiday List for Company {0}').format(frappe.bold(get_default_company())))
+	return holiday_list
diff --git a/erpnext/education/doctype/student_attendance_tool/student_attendance_tool.py b/erpnext/education/doctype/student_attendance_tool/student_attendance_tool.py
index be26440..028db91 100644
--- a/erpnext/education/doctype/student_attendance_tool/student_attendance_tool.py
+++ b/erpnext/education/doctype/student_attendance_tool/student_attendance_tool.py
@@ -20,10 +20,10 @@
 			student_list = frappe.get_list("Student Group Student", fields=["student", "student_name", "group_roll_number"] , \
 			filters={"parent": student_group, "active": 1}, order_by= "group_roll_number")
 
-	if not student_list: 
-		student_list = frappe.get_list("Student Group Student", fields=["student", "student_name", "group_roll_number"] , 
+	if not student_list:
+		student_list = frappe.get_list("Student Group Student", fields=["student", "student_name", "group_roll_number"] ,
 			filters={"parent": student_group, "active": 1}, order_by= "group_roll_number")
-	
+
 	if course_schedule:
 		student_attendance_list= frappe.db.sql('''select student, status from `tabStudent Attendance` where \
 			course_schedule= %s''', (course_schedule), as_dict=1)
@@ -32,7 +32,7 @@
 			student_group= %s and date= %s and \
 			(course_schedule is Null or course_schedule='')''',
 			(student_group, date), as_dict=1)
-	
+
 	for attendance in student_attendance_list:
 		for student in student_list:
 			if student.student == attendance.student:
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 ad53976..31b3da2 100644
--- a/erpnext/education/doctype/student_leave_application/student_leave_application.json
+++ b/erpnext/education/doctype/student_leave_application/student_leave_application.json
@@ -11,6 +11,7 @@
   "column_break_3",
   "from_date",
   "to_date",
+  "total_leave_days",
   "section_break_5",
   "attendance_based_on",
   "student_group",
@@ -110,11 +111,17 @@
   {
    "fieldname": "column_break_11",
    "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "total_leave_days",
+   "fieldtype": "Float",
+   "label": "Total Leave Days",
+   "read_only": 1
   }
  ],
  "is_submittable": 1,
  "links": [],
- "modified": "2020-07-08 13:22:38.329002",
+ "modified": "2020-09-21 18:10:24.440669",
  "modified_by": "Administrator",
  "module": "Education",
  "name": "Student Leave Application",
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 c8841c9..ef67012 100644
--- a/erpnext/education/doctype/student_leave_application/student_leave_application.py
+++ b/erpnext/education/doctype/student_leave_application/student_leave_application.py
@@ -6,11 +6,14 @@
 import frappe
 from frappe import _
 from datetime import timedelta
-from frappe.utils import get_link_to_form, getdate
+from frappe.utils import get_link_to_form, getdate, date_diff, flt
+from erpnext.hr.doctype.holiday_list.holiday_list import is_holiday
+from erpnext.education.doctype.student_attendance.student_attendance import get_holiday_list
 from frappe.model.document import Document
 
 class StudentLeaveApplication(Document):
 	def validate(self):
+		self.validate_holiday_list()
 		self.validate_duplicate()
 		self.validate_from_to_dates('from_date', 'to_date')
 
@@ -39,10 +42,19 @@
 			frappe.throw(_('Leave application {0} already exists against the student {1}')
 				.format(link, frappe.bold(self.student)), title=_('Duplicate Entry'))
 
+	def validate_holiday_list(self):
+		holiday_list = get_holiday_list()
+		self.total_leave_days = get_number_of_leave_days(self.from_date, self.to_date, holiday_list)
+
 	def update_attendance(self):
+		holiday_list = get_holiday_list()
+
 		for dt in daterange(getdate(self.from_date), getdate(self.to_date)):
 			date = dt.strftime('%Y-%m-%d')
 
+			if is_holiday(holiday_list, date):
+				continue
+
 			attendance = frappe.db.exists('Student Attendance', {
 				'student': self.student,
 				'date': date,
@@ -89,3 +101,19 @@
 def daterange(start_date, end_date):
 	for n in range(int ((end_date - start_date).days)+1):
 		yield start_date + timedelta(n)
+
+def get_number_of_leave_days(from_date, to_date, holiday_list):
+	number_of_days = date_diff(to_date, from_date) + 1
+
+	holidays = frappe.db.sql("""
+		SELECT
+			COUNT(DISTINCT holiday_date)
+		FROM `tabHoliday` h1,`tabHoliday List` h2
+		WHERE
+			h1.parent = h2.name and
+			h1.holiday_date between %s and %s and
+			h2.name = %s""", (from_date, to_date, holiday_list))[0][0]
+
+	number_of_days = flt(number_of_days) - flt(holidays)
+
+	return number_of_days
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 e9b568a..fcdd428 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,13 +5,15 @@
 
 import frappe
 import unittest
-from frappe.utils import getdate, add_days
+from frappe.utils import getdate, add_days, add_months
+from erpnext import get_default_company
 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):
 	def setUp(self):
 		frappe.db.sql("""delete from `tabStudent Leave Application`""")
+		create_holiday_list()
 
 	def test_attendance_record_creation(self):
 		leave_application = create_leave_application()
@@ -35,20 +37,45 @@
 		attendance_status = frappe.db.get_value('Student Attendance', {'leave_application': leave_application.name}, 'docstatus')
 		self.assertTrue(attendance_status, 2)
 
+	def test_holiday(self):
+		today = getdate()
+		leave_application = create_leave_application(from_date=today, to_date= add_days(today, 1), submit=0)
 
-def create_leave_application(from_date=None, to_date=None, mark_as_present=0):
+		# holiday list validation
+		company = get_default_company() or frappe.get_all('Company')[0].name
+		frappe.db.set_value('Company', company, 'default_holiday_list', '')
+		self.assertRaises(frappe.ValidationError, leave_application.save)
+
+		frappe.db.set_value('Company', company, 'default_holiday_list', 'Test Holiday List for Student')
+		leave_application.save()
+
+		leave_application.reload()
+		self.assertEqual(leave_application.total_leave_days, 1)
+
+		# check no attendance record created for a holiday
+		leave_application.submit()
+		self.assertIsNone(frappe.db.exists('Student Attendance', {'leave_application': leave_application.name, 'date': add_days(today, 1)}))
+
+	def tearDown(self):
+		company = get_default_company() or frappe.get_all('Company')[0].name
+		frappe.db.set_value('Company', company, 'default_holiday_list', '_Test Holiday List')
+
+
+def create_leave_application(from_date=None, to_date=None, mark_as_present=0, submit=1):
 	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()
+	leave_application = frappe.new_doc('Student Leave Application')
+	leave_application.student = student.name
+	leave_application.attendance_based_on = 'Student Group'
+	leave_application.student_group = get_random_group().name
+	leave_application.from_date = from_date if from_date else getdate()
+	leave_application.to_date = from_date if from_date else getdate()
+	leave_application.mark_as_present = mark_as_present
+
+	if submit:
+		leave_application.insert()
+		leave_application.submit()
+
 	return leave_application
 
 def create_student_attendance(date=None, status=None):
@@ -67,4 +94,22 @@
 		email='test_student@gmail.com',
 		first_name='Test',
 		last_name='Student'
-	))
\ No newline at end of file
+	))
+
+def create_holiday_list():
+	holiday_list = 'Test Holiday List for Student'
+	today = getdate()
+	if not frappe.db.exists('Holiday List', holiday_list):
+		frappe.get_doc(dict(
+			doctype = 'Holiday List',
+			holiday_list_name = holiday_list,
+			from_date = add_months(today, -6),
+			to_date = add_months(today, 6),
+			holidays = [
+				dict(holiday_date=add_days(today, 1), description = 'Test')
+			]
+		)).insert()
+
+	company = get_default_company() or frappe.get_all('Company')[0].name
+	frappe.db.set_value('Company', company, 'default_holiday_list', holiday_list)
+	return holiday_list
\ No newline at end of file
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 4e57cc6..c3487cc 100644
--- a/erpnext/education/report/absent_student_report/absent_student_report.py
+++ b/erpnext/education/report/absent_student_report/absent_student_report.py
@@ -3,8 +3,10 @@
 
 from __future__ import unicode_literals
 import frappe
-from frappe.utils import cstr, cint, getdate
+from frappe.utils import formatdate
 from frappe import msgprint, _
+from erpnext.education.doctype.student_attendance.student_attendance import get_holiday_list
+from erpnext.hr.doctype.holiday_list.holiday_list import is_holiday
 
 def execute(filters=None):
 	if not filters: filters = {}
@@ -15,6 +17,11 @@
 	columns = get_columns(filters)
 	date = filters.get("date")
 
+	holiday_list = get_holiday_list()
+	if is_holiday(holiday_list, filters.get("date")):
+		msgprint(_("No attendance has been marked for {0} as it is a Holiday").format(frappe.bold(formatdate(filters.get("date")))))
+
+
 	absent_students = get_absent_students(date)
 	leave_applicants = get_leave_applications(date)
 	if absent_students:
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 c65d233..7793dcf 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
@@ -3,8 +3,10 @@
 
 from __future__ import unicode_literals
 import frappe
-from frappe.utils import cstr, cint, getdate
+from frappe.utils import formatdate
 from frappe import msgprint, _
+from erpnext.education.doctype.student_attendance.student_attendance import get_holiday_list
+from erpnext.hr.doctype.holiday_list.holiday_list import is_holiday
 
 def execute(filters=None):
 	if not filters: filters = {}
@@ -12,6 +14,10 @@
 	if not filters.get("date"):
 		msgprint(_("Please select date"), raise_exception=1)
 
+	holiday_list = get_holiday_list()
+	if is_holiday(holiday_list, filters.get("date")):
+		msgprint(_("No attendance has been marked for {0} as it is a Holiday").format(frappe.bold(formatdate(filters.get("date")))))
+
 	columns = get_columns(filters)
 
 	active_student_group = get_active_student_group()
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 d820bfb..04dc8c0 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
@@ -7,6 +7,8 @@
 from frappe import msgprint, _
 from calendar import monthrange
 from erpnext.education.api import get_student_group_students
+from erpnext.education.doctype.student_attendance.student_attendance import get_holiday_list
+from erpnext.support.doctype.issue.issue import get_holidays
 
 def execute(filters=None):
 	if not filters: filters = {}
@@ -19,26 +21,32 @@
 	students_list = get_students_list(students)
 	att_map = get_attendance_list(from_date, to_date, filters.get("student_group"), students_list)
 	data = []
+
 	for stud in students:
 		row = [stud.student, stud.student_name]
 		student_status = frappe.db.get_value("Student", stud.student, "enabled")
 		date = from_date
 		total_p = total_a = 0.0
+
 		for day in range(total_days_in_month):
 			status="None"
+
 			if att_map.get(stud.student):
 				status = att_map.get(stud.student).get(date, "None")
 			elif not student_status:
 				status = "Inactive"
 			else:
 				status = "None"
-			status_map = {"Present": "P", "Absent": "A", "None": "", "Inactive":"-"}
+
+			status_map = {"Present": "P", "Absent": "A", "None": "", "Inactive":"-", "Holiday":"H"}
 			row.append(status_map[status])
+
 			if status == "Present":
 				total_p += 1
 			elif status == "Absent":
 				total_a += 1
 			date = add_days(date, 1)
+
 		row += [total_p, total_a]
 		data.append(row)
 	return columns, data
@@ -63,14 +71,19 @@
 		and date between %s and %s
 		order by student, date''',
 		(student_group, from_date, to_date), as_dict=1)
+
 	att_map = {}
 	students_with_leave_application = get_students_with_leave_application(from_date, to_date, students_list)
 	for d in attendance_list:
 		att_map.setdefault(d.student, frappe._dict()).setdefault(d.date, "")
+
 		if students_with_leave_application.get(d.date) and d.student in students_with_leave_application.get(d.date):
 			att_map[d.student][d.date] = "Present"
 		else:
 			att_map[d.student][d.date] = d.status
+
+	att_map = mark_holidays(att_map, from_date, to_date, students_list)
+
 	return att_map
 
 def get_students_with_leave_application(from_date, to_date, students_list):
@@ -108,3 +121,14 @@
 	if not year_list:
 		year_list = [getdate().year]
 	return "\n".join(str(year) for year in year_list)
+
+def mark_holidays(att_map, from_date, to_date, students_list):
+	holiday_list = get_holiday_list()
+	holidays = get_holidays(holiday_list)
+
+	for dt in daterange(getdate(from_date), getdate(to_date)):
+		if dt in holidays:
+			for student in students_list:
+				att_map.setdefault(student, frappe._dict()).setdefault(dt, "Holiday")
+
+	return att_map
diff --git a/erpnext/erpnext_integrations/connectors/shopify_connection.py b/erpnext/erpnext_integrations/connectors/shopify_connection.py
index d59f909..efbaa71 100644
--- a/erpnext/erpnext_integrations/connectors/shopify_connection.py
+++ b/erpnext/erpnext_integrations/connectors/shopify_connection.py
@@ -2,12 +2,13 @@
 import frappe
 from frappe import _
 import json
-from frappe.utils import cstr, cint, nowdate, flt
+from frappe.utils import cstr, cint, nowdate, getdate, flt, get_request_session, get_datetime
 from erpnext.erpnext_integrations.utils import validate_webhooks_request
 from erpnext.selling.doctype.sales_order.sales_order import make_delivery_note, make_sales_invoice
 from erpnext.erpnext_integrations.doctype.shopify_settings.sync_product import sync_item_from_shopify
 from erpnext.erpnext_integrations.doctype.shopify_settings.sync_customer import create_customer
 from erpnext.erpnext_integrations.doctype.shopify_log.shopify_log import make_shopify_log, dump_request_data
+from erpnext.erpnext_integrations.doctype.shopify_settings.shopify_settings import get_shopify_url, get_header
 
 @frappe.whitelist(allow_guest=True)
 @validate_webhooks_request("Shopify Settings", 'X-Shopify-Hmac-Sha256', secret_key='shared_secret')
@@ -18,7 +19,7 @@
 
 	dump_request_data(order, event)
 
-def sync_sales_order(order, request_id=None):
+def sync_sales_order(order, request_id=None, old_order_sync=False):
 	frappe.set_user('Administrator')
 	shopify_settings = frappe.get_doc("Shopify Settings")
 	frappe.flags.request_id = request_id
@@ -27,7 +28,7 @@
 		try:
 			validate_customer(order, shopify_settings)
 			validate_item(order, shopify_settings)
-			create_order(order, shopify_settings)
+			create_order(order, shopify_settings, old_order_sync=old_order_sync)
 		except Exception as e:
 			make_shopify_log(status="Error", exception=e)
 
@@ -77,13 +78,13 @@
 		if item.get("product_id") and not frappe.db.get_value("Item", {"shopify_product_id": item.get("product_id")}, "name"):
 			sync_item_from_shopify(shopify_settings, item)
 
-def create_order(order, shopify_settings, company=None):
+def create_order(order, shopify_settings, old_order_sync=False, company=None):
 	so = create_sales_order(order, shopify_settings, company)
 	if so:
 		if order.get("financial_status") == "paid":
-			create_sales_invoice(order, shopify_settings, so)
+			create_sales_invoice(order, shopify_settings, so, old_order_sync=old_order_sync)
 
-		if order.get("fulfillments"):
+		if order.get("fulfillments") and not old_order_sync:
 			create_delivery_note(order, shopify_settings, so)
 
 def create_sales_order(shopify_order, shopify_settings, company=None):
@@ -92,7 +93,7 @@
 	so = frappe.db.get_value("Sales Order", {"shopify_order_id": shopify_order.get("id")}, "name")
 
 	if not so:
-		items = get_order_items(shopify_order.get("line_items"), shopify_settings)
+		items = get_order_items(shopify_order.get("line_items"), shopify_settings, getdate(shopify_order.get('created_at')))
 
 		if not items:
 			message = 'Following items exists in the shopify order but relevant records were not found in the shopify Product master'
@@ -106,8 +107,10 @@
 			"doctype": "Sales Order",
 			"naming_series": shopify_settings.sales_order_series or "SO-Shopify-",
 			"shopify_order_id": shopify_order.get("id"),
+			"shopify_order_number": shopify_order.get("name"),
 			"customer": customer or shopify_settings.default_customer,
-			"delivery_date": nowdate(),
+			"transaction_date": getdate(shopify_order.get("created_at")) or nowdate(),
+			"delivery_date": getdate(shopify_order.get("created_at")) or nowdate(),
 			"company": shopify_settings.company,
 			"selling_price_list": shopify_settings.price_list,
 			"ignore_pricing_rule": 1,
@@ -132,32 +135,42 @@
 	frappe.db.commit()
 	return so
 
-def create_sales_invoice(shopify_order, shopify_settings, so):
+def create_sales_invoice(shopify_order, shopify_settings, so, old_order_sync=False):
 	if not frappe.db.get_value("Sales Invoice", {"shopify_order_id": shopify_order.get("id")}, "name")\
 		and so.docstatus==1 and not so.per_billed and cint(shopify_settings.sync_sales_invoice):
 
+		if old_order_sync:
+			posting_date = getdate(shopify_order.get('created_at'))
+		else:
+			posting_date = nowdate()
+
 		si = make_sales_invoice(so.name, ignore_permissions=True)
 		si.shopify_order_id = shopify_order.get("id")
+		si.shopify_order_number = shopify_order.get("name")
+		si.set_posting_time = 1
+		si.posting_date = posting_date
+		si.due_date = posting_date
 		si.naming_series = shopify_settings.sales_invoice_series or "SI-Shopify-"
 		si.flags.ignore_mandatory = True
 		set_cost_center(si.items, shopify_settings.cost_center)
 		si.insert(ignore_mandatory=True)
 		si.submit()
-		make_payament_entry_against_sales_invoice(si, shopify_settings)
+		make_payament_entry_against_sales_invoice(si, shopify_settings, posting_date)
 		frappe.db.commit()
 
 def set_cost_center(items, cost_center):
 	for item in items:
 		item.cost_center = cost_center
 
-def make_payament_entry_against_sales_invoice(doc, shopify_settings):
+def make_payament_entry_against_sales_invoice(doc, shopify_settings, posting_date=None):
 	from erpnext.accounts.doctype.payment_entry.payment_entry import get_payment_entry
-	payemnt_entry = get_payment_entry(doc.doctype, doc.name, bank_account=shopify_settings.cash_bank_account)
-	payemnt_entry.flags.ignore_mandatory = True
-	payemnt_entry.reference_no = doc.name
-	payemnt_entry.reference_date = nowdate()
-	payemnt_entry.insert(ignore_permissions=True)
-	payemnt_entry.submit()
+	payment_entry = get_payment_entry(doc.doctype, doc.name, bank_account=shopify_settings.cash_bank_account)
+	payment_entry.flags.ignore_mandatory = True
+	payment_entry.reference_no = doc.name
+	payment_entry.posting_date = posting_date or nowdate()
+	payment_entry.reference_date = posting_date or nowdate()
+	payment_entry.insert(ignore_permissions=True)
+	payment_entry.submit()
 
 def create_delivery_note(shopify_order, shopify_settings, so):
 	if not cint(shopify_settings.sync_delivery_note):
@@ -169,6 +182,9 @@
 
 			dn = make_delivery_note(so.name)
 			dn.shopify_order_id = fulfillment.get("order_id")
+			dn.shopify_order_number = shopify_order.get("name")
+			dn.set_posting_time = 1
+			dn.posting_date = getdate(fulfillment.get("created_at"))
 			dn.shopify_fulfillment_id = fulfillment.get("id")
 			dn.naming_series = shopify_settings.delivery_note_series or "DN-Shopify-"
 			dn.items = get_fulfillment_items(dn.items, fulfillment.get("line_items"), shopify_settings)
@@ -187,7 +203,7 @@
 		discounted_amount += flt(discount.get("amount"))
 	return discounted_amount
 
-def get_order_items(order_items, shopify_settings):
+def get_order_items(order_items, shopify_settings, delivery_date):
 	items = []
 	all_product_exists = True
 	product_not_exists = []
@@ -205,7 +221,7 @@
 				"item_code": item_code,
 				"item_name": shopify_item.get("name"),
 				"rate": shopify_item.get("price"),
-				"delivery_date": nowdate(),
+				"delivery_date": delivery_date,
 				"qty": shopify_item.get("quantity"),
 				"stock_uom": shopify_item.get("uom") or _("Nos"),
 				"warehouse": shopify_settings.warehouse
@@ -265,3 +281,64 @@
 		frappe.throw(_("Tax Account not specified for Shopify Tax {0}").format(tax.get("title")))
 
 	return tax_account
+
+@frappe.whitelist(allow_guest=True)
+def sync_old_orders():
+	frappe.set_user('Administrator')
+	shopify_settings = frappe.get_doc('Shopify Settings')
+
+	if not shopify_settings.sync_missing_orders:
+		return
+
+	url = get_url(shopify_settings)
+	session = get_request_session()
+
+	try:
+		res = session.get(url, headers=get_header(shopify_settings))
+		res.raise_for_status()
+		orders = res.json()["orders"]
+
+		for order in orders:
+			if is_sync_complete(shopify_settings, order):
+				stop_sync(shopify_settings)
+				return
+
+			sync_sales_order(order=order, old_order_sync=True)
+			last_order_id = order.get('id')
+
+		if last_order_id:
+			shopify_settings.load_from_db()
+			shopify_settings.last_order_id = last_order_id
+			shopify_settings.save()
+			frappe.db.commit()
+
+	except Exception as e:
+		raise e
+
+def stop_sync(shopify_settings):
+	shopify_settings.sync_missing_orders = 0
+	shopify_settings.last_order_id = ''
+	shopify_settings.save()
+	frappe.db.commit()
+
+def get_url(shopify_settings):
+	last_order_id = shopify_settings.last_order_id
+
+	if not last_order_id:
+		if shopify_settings.sync_based_on == 'Date':
+			url = get_shopify_url("admin/api/2020-10/orders.json?limit=250&created_at_min={0}&since_id=0".format(
+				get_datetime(shopify_settings.from_date)), shopify_settings)
+		else:
+			url = get_shopify_url("admin/api/2020-10/orders.json?limit=250&since_id={0}".format(
+				shopify_settings.from_order_id), shopify_settings)
+	else:
+		url = get_shopify_url("admin/api/2020-10/orders.json?limit=250&since_id={0}".format(last_order_id), shopify_settings)
+
+	return url
+
+def is_sync_complete(shopify_settings, order):
+	if shopify_settings.sync_based_on == 'Date':
+		return getdate(shopify_settings.to_date) < getdate(order.get('created_at'))
+	else:
+		return cstr(order.get('id')) == cstr(shopify_settings.to_order_id)
+
diff --git a/erpnext/erpnext_integrations/doctype/shopify_settings/shopify_settings.json b/erpnext/erpnext_integrations/doctype/shopify_settings/shopify_settings.json
index 2e10751..20ec063 100644
--- a/erpnext/erpnext_integrations/doctype/shopify_settings/shopify_settings.json
+++ b/erpnext/erpnext_integrations/doctype/shopify_settings/shopify_settings.json
@@ -1,7 +1,9 @@
 {
+ "actions": [],
  "creation": "2015-05-18 05:21:07.270859",
  "doctype": "DocType",
  "document_type": "System",
+ "engine": "InnoDB",
  "field_order": [
   "status_html",
   "enable_shopify",
@@ -40,7 +42,16 @@
   "sales_invoice_series",
   "section_break_22",
   "html_16",
-  "taxes"
+  "taxes",
+  "syncing_details_section",
+  "sync_missing_orders",
+  "sync_based_on",
+  "column_break_41",
+  "from_date",
+  "to_date",
+  "from_order_id",
+  "to_order_id",
+  "last_order_id"
  ],
  "fields": [
   {
@@ -255,10 +266,71 @@
    "fieldtype": "Table",
    "label": "Shopify Tax Account",
    "options": "Shopify Tax Account"
+  },
+  {
+   "collapsible": 1,
+   "fieldname": "syncing_details_section",
+   "fieldtype": "Section Break",
+   "label": "Syncing Missing Orders"
+  },
+  {
+   "depends_on": "eval:doc.sync_missing_orders",
+   "fieldname": "last_order_id",
+   "fieldtype": "Data",
+   "label": "Last Order Id",
+   "read_only": 1
+  },
+  {
+   "fieldname": "column_break_41",
+   "fieldtype": "Column Break"
+  },
+  {
+   "default": "0",
+   "description": "On checking this Order from the ",
+   "fieldname": "sync_missing_orders",
+   "fieldtype": "Check",
+   "label": "Sync Missing Old Shopify Orders"
+  },
+  {
+   "depends_on": "eval:doc.sync_missing_orders",
+   "fieldname": "sync_based_on",
+   "fieldtype": "Select",
+   "label": "Sync Based On",
+   "mandatory_depends_on": "eval:doc.sync_missing_orders",
+   "options": "\nDate\nShopify Order Id"
+  },
+  {
+   "depends_on": "eval:doc.sync_based_on == 'Date' && doc.sync_missing_orders",
+   "fieldname": "from_date",
+   "fieldtype": "Date",
+   "label": "From Date",
+   "mandatory_depends_on": "eval:doc.sync_based_on == 'Date' && doc.sync_missing_orders"
+  },
+  {
+   "depends_on": "eval:doc.sync_based_on == 'Date' && doc.sync_missing_orders",
+   "fieldname": "to_date",
+   "fieldtype": "Date",
+   "label": "To Date",
+   "mandatory_depends_on": "eval:doc.sync_based_on == 'Date' && doc.sync_missing_orders"
+  },
+  {
+   "depends_on": "eval:doc.sync_based_on == 'Shopify Order Id' && doc.sync_missing_orders",
+   "fieldname": "from_order_id",
+   "fieldtype": "Data",
+   "label": "From Order Id",
+   "mandatory_depends_on": "eval:doc.sync_based_on == 'Shopify Order Id' && doc.sync_missing_orders"
+  },
+  {
+   "depends_on": "eval:doc.sync_based_on == 'Shopify Order Id' && doc.sync_missing_orders",
+   "fieldname": "to_order_id",
+   "fieldtype": "Data",
+   "label": "To Order Id",
+   "mandatory_depends_on": "eval:doc.sync_based_on == 'Shopify Order Id' && doc.sync_missing_orders"
   }
  ],
  "issingle": 1,
- "modified": "2020-09-18 17:26:09.703215",
+ "links": [],
+ "modified": "2020-11-05 20:44:03.664891",
  "modified_by": "Administrator",
  "module": "ERPNext Integrations",
  "name": "Shopify Settings",
@@ -277,4 +349,4 @@
  ],
  "sort_field": "modified",
  "sort_order": "DESC"
-}
+}
\ No newline at end of file
diff --git a/erpnext/erpnext_integrations/doctype/shopify_settings/shopify_settings.py b/erpnext/erpnext_integrations/doctype/shopify_settings/shopify_settings.py
index 25ffd28..cbdf906 100644
--- a/erpnext/erpnext_integrations/doctype/shopify_settings/shopify_settings.py
+++ b/erpnext/erpnext_integrations/doctype/shopify_settings/shopify_settings.py
@@ -87,7 +87,7 @@
 def get_header(settings):
 	header = {'Content-Type': 'application/json'}
 
-	return header;
+	return header
 
 @frappe.whitelist()
 def get_series():
@@ -121,17 +121,23 @@
 		],
 		"Sales Order": [
 			dict(fieldname='shopify_order_id', label='Shopify Order Id',
-				fieldtype='Data', insert_after='title', read_only=1, print_hide=1)
+				fieldtype='Data', insert_after='title', read_only=1, print_hide=1),
+			dict(fieldname='shopify_order_number', label='Shopify Order Number',
+				fieldtype='Data', insert_after='shopify_order_id', read_only=1, print_hide=1)
 		],
 		"Delivery Note":[
 			dict(fieldname='shopify_order_id', label='Shopify Order Id',
 				fieldtype='Data', insert_after='title', read_only=1, print_hide=1),
+			dict(fieldname='shopify_order_number', label='Shopify Order Number',
+				fieldtype='Data', insert_after='shopify_order_id', read_only=1, print_hide=1),
 			dict(fieldname='shopify_fulfillment_id', label='Shopify Fulfillment Id',
 				fieldtype='Data', insert_after='title', read_only=1, print_hide=1)
 		],
 		"Sales Invoice": [
 			dict(fieldname='shopify_order_id', label='Shopify Order Id',
-				fieldtype='Data', insert_after='title', read_only=1, print_hide=1)
+				fieldtype='Data', insert_after='title', read_only=1, print_hide=1),
+			dict(fieldname='shopify_order_number', label='Shopify Order Number',
+				fieldtype='Data', insert_after='shopify_order_id', read_only=1, print_hide=1)
 		]
 	}
 
diff --git a/erpnext/erpnext_integrations/doctype/shopify_settings/test_shopify_settings.py b/erpnext/erpnext_integrations/doctype/shopify_settings/test_shopify_settings.py
index 64ef3dc..30fa23c 100644
--- a/erpnext/erpnext_integrations/doctype/shopify_settings/test_shopify_settings.py
+++ b/erpnext/erpnext_integrations/doctype/shopify_settings/test_shopify_settings.py
@@ -58,7 +58,7 @@
 		}).save(ignore_permissions=True)
 
 		self.shopify_settings = shopify_settings
-	
+
 	def test_order(self):
 		### Create Customer ###
 		with open (os.path.join(os.path.dirname(__file__), "test_data", "shopify_customer.json")) as shopify_customer:
@@ -75,7 +75,7 @@
 		with open (os.path.join(os.path.dirname(__file__), "test_data", "shopify_order.json")) as shopify_order:
 			shopify_order = json.load(shopify_order)
 
-		create_order(shopify_order.get("order"), self.shopify_settings, "_Test Company")
+		create_order(shopify_order.get("order"), self.shopify_settings, False, company="_Test Company")
 
 		sales_order = frappe.get_doc("Sales Order", {"shopify_order_id": cstr(shopify_order.get("order").get("id"))})
 
diff --git a/erpnext/healthcare/desk_page/healthcare/healthcare.json b/erpnext/healthcare/desk_page/healthcare/healthcare.json
index 6546b08..81d6048 100644
--- a/erpnext/healthcare/desk_page/healthcare/healthcare.json
+++ b/erpnext/healthcare/desk_page/healthcare/healthcare.json
@@ -43,7 +43,7 @@
   {
    "hidden": 0,
    "label": "Reports",
-   "links": "[\n\t{\n\t\t\"type\": \"report\",\n\t\t\"is_query_report\": true,\n\t\t\"name\": \"Patient Appointment Analytics\",\n\t\t\"doctype\": \"Patient Appointment\"\n\t},\n\t{\n\t\t\"type\": \"report\",\n\t\t\"is_query_report\": true,\n\t\t\"name\": \"Lab Test Report\",\n\t\t\"doctype\": \"Lab Test\",\n\t\t\"label\": \"Lab Test Report\"\n\t}\n]"
+   "links": "[\n\t{\n\t\t\"type\": \"report\",\n\t\t\"is_query_report\": true,\n\t\t\"name\": \"Patient Appointment Analytics\",\n\t\t\"doctype\": \"Patient Appointment\"\n\t},\n\t{\n\t\t\"type\": \"report\",\n\t\t\"is_query_report\": true,\n\t\t\"name\": \"Lab Test Report\",\n\t\t\"doctype\": \"Lab Test\",\n\t\t\"label\": \"Lab Test Report\"\n\t},\n\t{\n\t\t\"type\": \"report\",\n\t\t\"is_query_report\": true,\n\t\t\"name\": \"Inpatient Medication Orders\",\n\t\t\"doctype\": \"Inpatient Medication Order\",\n\t\t\"label\": \"Inpatient Medication Orders\"\n\t}\n]"
   }
  ],
  "category": "Domains",
@@ -64,7 +64,7 @@
  "idx": 0,
  "is_standard": 1,
  "label": "Healthcare",
- "modified": "2020-06-25 23:50:56.951698",
+ "modified": "2020-11-23 23:00:48.764377",
  "modified_by": "Administrator",
  "module": "Healthcare",
  "name": "Healthcare",
diff --git a/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.js b/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.js
index eb7d4bd..1d4411d 100644
--- a/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.js
+++ b/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.js
@@ -85,8 +85,7 @@
 								callback: function(r) {
 									if (r.message) {
 										frappe.show_alert({
-											message:  __('Stock Entry {0} created',
-												['<a class="bold" href="#Form/Stock Entry/'+ r.message + '">' + r.message + '</a>']),
+											message: __('Stock Entry {0} created', ['<a class="bold" href="#Form/Stock Entry/'+ r.message + '">' + r.message + '</a>']),
 											indicator: 'green'
 										});
 									}
@@ -105,8 +104,7 @@
 						callback: function(r) {
 							if (!r.exc) {
 								if (r.message == 'insufficient stock') {
-									let msg = __('Stock quantity to start the Procedure is not available in the Warehouse {0}. Do you want to record a Stock Entry?',
-										[frm.doc.warehouse.bold()]);
+									let msg = __('Stock quantity to start the Procedure is not available in the Warehouse {0}. Do you want to record a Stock Entry?', [frm.doc.warehouse.bold()]);
 									frappe.confirm(
 										msg,
 										function() {
diff --git a/erpnext/healthcare/doctype/inpatient_medication_entry/inpatient_medication_entry.py b/erpnext/healthcare/doctype/inpatient_medication_entry/inpatient_medication_entry.py
index 23e7519..5dac23a 100644
--- a/erpnext/healthcare/doctype/inpatient_medication_entry/inpatient_medication_entry.py
+++ b/erpnext/healthcare/doctype/inpatient_medication_entry/inpatient_medication_entry.py
@@ -274,4 +274,6 @@
 
 def get_current_healthcare_service_unit(inpatient_record):
 	ip_record = frappe.get_doc('Inpatient Record', inpatient_record)
-	return ip_record.inpatient_occupancies[-1].service_unit
\ No newline at end of file
+	if ip_record.inpatient_occupancies:
+		return ip_record.inpatient_occupancies[-1].service_unit
+	return
\ No newline at end of file
diff --git a/erpnext/healthcare/report/inpatient_medication_orders/__init__.py b/erpnext/healthcare/report/inpatient_medication_orders/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/healthcare/report/inpatient_medication_orders/__init__.py
diff --git a/erpnext/healthcare/report/inpatient_medication_orders/inpatient_medication_orders.js b/erpnext/healthcare/report/inpatient_medication_orders/inpatient_medication_orders.js
new file mode 100644
index 0000000..a10f837
--- /dev/null
+++ b/erpnext/healthcare/report/inpatient_medication_orders/inpatient_medication_orders.js
@@ -0,0 +1,57 @@
+// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+/* eslint-disable */
+
+frappe.query_reports["Inpatient Medication Orders"] = {
+	"filters": [
+		{
+			fieldname: "company",
+			label: __("Company"),
+			fieldtype: "Link",
+			options: "Company",
+			default: frappe.defaults.get_user_default("Company"),
+			reqd: 1
+		},
+		{
+			fieldname: "from_date",
+			label: __("From Date"),
+			fieldtype: "Date",
+			default: frappe.datetime.add_months(frappe.datetime.get_today(), -1),
+			reqd: 1
+		},
+		{
+			fieldname: "to_date",
+			label: __("To Date"),
+			fieldtype: "Date",
+			default: frappe.datetime.now_date(),
+			reqd: 1
+		},
+		{
+			fieldname: "patient",
+			label: __("Patient"),
+			fieldtype: "Link",
+			options: "Patient"
+		},
+		{
+			fieldname: "service_unit",
+			label: __("Healthcare Service Unit"),
+			fieldtype: "Link",
+			options: "Healthcare Service Unit",
+			get_query: () => {
+				var company = frappe.query_report.get_filter_value('company');
+				return {
+					filters: {
+						'company': company,
+						'is_group': 0
+					}
+				}
+			}
+		},
+		{
+			fieldname: "show_completed_orders",
+			label: __("Show Completed Orders"),
+			fieldtype: "Check",
+			default: 1
+		}
+	]
+};
diff --git a/erpnext/healthcare/report/inpatient_medication_orders/inpatient_medication_orders.json b/erpnext/healthcare/report/inpatient_medication_orders/inpatient_medication_orders.json
new file mode 100644
index 0000000..9217fa1
--- /dev/null
+++ b/erpnext/healthcare/report/inpatient_medication_orders/inpatient_medication_orders.json
@@ -0,0 +1,36 @@
+{
+ "add_total_row": 0,
+ "columns": [],
+ "creation": "2020-11-23 17:25:58.802949",
+ "disable_prepared_report": 0,
+ "disabled": 0,
+ "docstatus": 0,
+ "doctype": "Report",
+ "filters": [],
+ "idx": 0,
+ "is_standard": "Yes",
+ "json": "{}",
+ "modified": "2020-11-23 19:40:20.227591",
+ "modified_by": "Administrator",
+ "module": "Healthcare",
+ "name": "Inpatient Medication Orders",
+ "owner": "Administrator",
+ "prepared_report": 0,
+ "ref_doctype": "Inpatient Medication Order",
+ "report_name": "Inpatient Medication Orders",
+ "report_type": "Script Report",
+ "roles": [
+  {
+   "role": "System Manager"
+  },
+  {
+   "role": "Healthcare Administrator"
+  },
+  {
+   "role": "Nursing User"
+  },
+  {
+   "role": "Physician"
+  }
+ ]
+}
\ No newline at end of file
diff --git a/erpnext/healthcare/report/inpatient_medication_orders/inpatient_medication_orders.py b/erpnext/healthcare/report/inpatient_medication_orders/inpatient_medication_orders.py
new file mode 100644
index 0000000..b907730
--- /dev/null
+++ b/erpnext/healthcare/report/inpatient_medication_orders/inpatient_medication_orders.py
@@ -0,0 +1,198 @@
+# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+from erpnext.healthcare.doctype.inpatient_medication_entry.inpatient_medication_entry import get_current_healthcare_service_unit
+
+def execute(filters=None):
+	columns = get_columns()
+	data = get_data(filters)
+	chart = get_chart_data(data)
+
+	return columns, data, None, chart
+
+def get_columns():
+	return [
+		{
+			"fieldname": "patient",
+			"fieldtype": "Link",
+			"label": "Patient",
+			"options": "Patient",
+			"width": 200
+		},
+		{
+			"fieldname": "healthcare_service_unit",
+			"fieldtype": "Link",
+			"label": "Healthcare Service Unit",
+			"options": "Healthcare Service Unit",
+			"width": 150
+		},
+		{
+			"fieldname": "drug",
+			"fieldtype": "Link",
+			"label": "Drug Code",
+			"options": "Item",
+			"width": 150
+		},
+		{
+			"fieldname": "drug_name",
+			"fieldtype": "Data",
+			"label": "Drug Name",
+			"width": 150
+		},
+		{
+			"fieldname": "dosage",
+			"fieldtype": "Link",
+			"label": "Dosage",
+			"options": "Prescription Dosage",
+			"width": 80
+		},
+		{
+			"fieldname": "dosage_form",
+			"fieldtype": "Link",
+			"label": "Dosage Form",
+			"options": "Dosage Form",
+			"width": 100
+		},
+		{
+			"fieldname": "date",
+			"fieldtype": "Date",
+			"label": "Date",
+			"width": 100
+		},
+		{
+			"fieldname": "time",
+			"fieldtype": "Time",
+			"label": "Time",
+			"width": 100
+		},
+		{
+			"fieldname": "is_completed",
+			"fieldtype": "Check",
+			"label": "Is Order Completed",
+			"width": 100
+		},
+		{
+			"fieldname": "healthcare_practitioner",
+			"fieldtype": "Link",
+			"label": "Healthcare Practitioner",
+			"options": "Healthcare Practitioner",
+			"width": 200
+		},
+		{
+			"fieldname": "inpatient_medication_entry",
+			"fieldtype": "Link",
+			"label": "Inpatient Medication Entry",
+			"options": "Inpatient Medication Entry",
+			"width": 200
+		},
+		{
+			"fieldname": "inpatient_record",
+			"fieldtype": "Link",
+			"label": "Inpatient Record",
+			"options": "Inpatient Record",
+			"width": 200
+		}
+	]
+
+def get_data(filters):
+	conditions, values = get_conditions(filters)
+
+	data = frappe.db.sql("""
+		SELECT
+			parent.patient, parent.inpatient_record, parent.practitioner,
+			child.drug, child.drug_name, child.dosage, child.dosage_form,
+			child.date, child.time, child.is_completed, child.name
+		FROM `tabInpatient Medication Order` parent
+		INNER JOIN `tabInpatient Medication Order Entry` child
+		ON child.parent = parent.name
+		WHERE
+			parent.docstatus = 1
+			{conditions}
+		ORDER BY date, time
+	""".format(conditions=conditions), values, as_dict=1)
+
+	data = get_inpatient_details(data, filters.get("service_unit"))
+
+	return data
+
+def get_conditions(filters):
+	conditions = ""
+	values = dict()
+
+	if filters.get("company"):
+		conditions += " AND parent.company = %(company)s"
+		values["company"] = filters.get("company")
+
+	if filters.get("from_date") and filters.get("to_date"):
+		conditions += " AND child.date BETWEEN %(from_date)s and %(to_date)s"
+		values["from_date"] = filters.get("from_date")
+		values["to_date"] = filters.get("to_date")
+
+	if filters.get("patient"):
+		conditions += " AND parent.patient = %(patient)s"
+		values["patient"] = filters.get("patient")
+
+	if not filters.get("show_completed_orders"):
+		conditions += " AND child.is_completed = 0"
+
+	return conditions, values
+
+
+def get_inpatient_details(data, service_unit):
+	service_unit_filtered_data = []
+
+	for entry in data:
+		entry["healthcare_service_unit"] = get_current_healthcare_service_unit(entry.inpatient_record)
+		if entry.is_completed:
+			entry["inpatient_medication_entry"] = get_inpatient_medication_entry(entry.name)
+
+		if service_unit and entry.healthcare_service_unit and service_unit != entry.healthcare_service_unit:
+			service_unit_filtered_data.append(entry)
+
+		entry.pop("name", None)
+
+	for entry in service_unit_filtered_data:
+		data.remove(entry)
+
+	return data
+
+def get_inpatient_medication_entry(order_entry):
+	return frappe.db.get_value("Inpatient Medication Entry Detail", {"against_imoe": order_entry}, "parent")
+
+def get_chart_data(data):
+	if not data:
+		return None
+
+	labels = ["Pending", "Completed"]
+	datasets = []
+
+	status_wise_data = {
+		"Pending": 0,
+		"Completed": 0
+	}
+
+	for d in data:
+		if d.is_completed:
+			status_wise_data["Completed"] += 1
+		else:
+			status_wise_data["Pending"] += 1
+
+	datasets.append({
+		"name": "Inpatient Medication Order Status",
+		"values": [status_wise_data.get("Pending"), status_wise_data.get("Completed")]
+	})
+
+	chart = {
+		"data": {
+			"labels": labels,
+			"datasets": datasets
+		},
+		"type": "donut",
+		"height": 300
+	}
+
+	chart["fieldtype"] = "Data"
+
+	return chart
\ No newline at end of file
diff --git a/erpnext/healthcare/report/inpatient_medication_orders/test_inpatient_medication_orders.py b/erpnext/healthcare/report/inpatient_medication_orders/test_inpatient_medication_orders.py
new file mode 100644
index 0000000..0d3f45f
--- /dev/null
+++ b/erpnext/healthcare/report/inpatient_medication_orders/test_inpatient_medication_orders.py
@@ -0,0 +1,128 @@
+# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
+# License: GNU General Public License v3. See license.txt
+
+from __future__ import unicode_literals
+import unittest
+import frappe
+import datetime
+from frappe.utils import getdate, now_datetime
+from erpnext.healthcare.doctype.inpatient_record.test_inpatient_record import create_patient, create_inpatient, get_healthcare_service_unit, mark_invoiced_inpatient_occupancy
+from erpnext.healthcare.doctype.inpatient_record.inpatient_record import admit_patient, discharge_patient, schedule_discharge
+from erpnext.healthcare.doctype.inpatient_medication_order.test_inpatient_medication_order import create_ipmo, create_ipme
+from erpnext.healthcare.report.inpatient_medication_orders.inpatient_medication_orders import execute
+
+class TestInpatientMedicationOrders(unittest.TestCase):
+	@classmethod
+	def setUpClass(self):
+		frappe.db.sql("delete from `tabInpatient Medication Order` where company='_Test Company'")
+		frappe.db.sql("delete from `tabInpatient Medication Entry` where company='_Test Company'")
+		self.patient = create_patient()
+		self.ip_record = create_records(self.patient)
+
+	def test_inpatient_medication_orders_report(self):
+		filters = {
+			'company': '_Test Company',
+			'from_date': getdate(),
+			'to_date': getdate(),
+			'patient': '_Test IPD Patient',
+			'service_unit': 'Test Service Unit Ip Occupancy - _TC'
+		}
+
+		report = execute(filters)
+
+		expected_data = [
+			{
+				'patient': '_Test IPD Patient',
+				'inpatient_record': self.ip_record.name,
+				'practitioner': None,
+				'drug': 'Dextromethorphan',
+				'drug_name': 'Dextromethorphan',
+				'dosage': 1.0,
+				'dosage_form': 'Tablet',
+				'date': getdate(),
+				'time': datetime.timedelta(seconds=32400),
+				'is_completed': 0,
+				'healthcare_service_unit': 'Test Service Unit Ip Occupancy - _TC'
+			},
+			{
+				'patient': '_Test IPD Patient',
+				'inpatient_record': self.ip_record.name,
+				'practitioner': None,
+				'drug': 'Dextromethorphan',
+				'drug_name': 'Dextromethorphan',
+				'dosage': 1.0,
+				'dosage_form': 'Tablet',
+				'date': getdate(),
+				'time': datetime.timedelta(seconds=50400),
+				'is_completed': 0,
+				'healthcare_service_unit': 'Test Service Unit Ip Occupancy - _TC'
+			},
+			{
+				'patient': '_Test IPD Patient',
+				'inpatient_record': self.ip_record.name,
+				'practitioner': None,
+				'drug': 'Dextromethorphan',
+				'drug_name': 'Dextromethorphan',
+				'dosage': 1.0,
+				'dosage_form': 'Tablet',
+				'date': getdate(),
+				'time': datetime.timedelta(seconds=75600),
+				'is_completed': 0,
+				'healthcare_service_unit': 'Test Service Unit Ip Occupancy - _TC'
+			}
+		]
+
+		self.assertEqual(expected_data, report[1])
+
+		filters = frappe._dict(from_date=getdate(), to_date=getdate(), from_time='', to_time='')
+		ipme = create_ipme(filters)
+		ipme.submit()
+
+		filters = {
+			'company': '_Test Company',
+			'from_date': getdate(),
+			'to_date': getdate(),
+			'patient': '_Test IPD Patient',
+			'service_unit': 'Test Service Unit Ip Occupancy - _TC',
+			'show_completed_orders': 0
+		}
+
+		report = execute(filters)
+		self.assertEqual(len(report[1]), 0)
+
+	def tearDown(self):
+		if frappe.db.get_value('Patient', self.patient, 'inpatient_record'):
+			# cleanup - Discharge
+			schedule_discharge(frappe.as_json({'patient': self.patient}))
+			self.ip_record.reload()
+			mark_invoiced_inpatient_occupancy(self.ip_record)
+
+			self.ip_record.reload()
+			discharge_patient(self.ip_record)
+
+		for entry in frappe.get_all('Inpatient Medication Entry'):
+			doc = frappe.get_doc('Inpatient Medication Entry', entry.name)
+			doc.cancel()
+			doc.delete()
+
+		for entry in frappe.get_all('Inpatient Medication Order'):
+			doc = frappe.get_doc('Inpatient Medication Order', entry.name)
+			doc.cancel()
+			doc.delete()
+
+
+def create_records(patient):
+	frappe.db.sql("""delete from `tabInpatient Record`""")
+
+	# Admit
+	ip_record = create_inpatient(patient)
+	ip_record.expected_length_of_stay = 0
+	ip_record.save()
+	ip_record.reload()
+	service_unit = get_healthcare_service_unit()
+	admit_patient(ip_record, service_unit, now_datetime())
+
+	ipmo = create_ipmo(patient)
+	ipmo.submit()
+
+	return ip_record
diff --git a/erpnext/hooks.py b/erpnext/hooks.py
index dbb6c0d..726ab6e 100644
--- a/erpnext/hooks.py
+++ b/erpnext/hooks.py
@@ -15,10 +15,10 @@
 
 develop_version = '13.x.x-develop'
 
-app_include_js = "assets/js/erpnext.min.js"
-app_include_css = "assets/css/erpnext.css"
-web_include_js = "assets/js/erpnext-web.min.js"
-web_include_css = "assets/css/erpnext-web.css"
+app_include_js = "/assets/js/erpnext.min.js"
+app_include_css = "/assets/css/erpnext.css"
+web_include_js = "/assets/js/erpnext-web.min.js"
+web_include_css = "/assets/css/erpnext-web.css"
 
 doctype_js = {
 	"Address": "public/js/address.js",
@@ -237,6 +237,9 @@
 	"Website Settings": {
 		"validate": "erpnext.portal.doctype.products_settings.products_settings.home_page_is_products"
 	},
+	"Tax Category": {
+		"validate": "erpnext.regional.india.utils.validate_tax_category"
+	},
 	"Sales Invoice": {
 		"on_submit": [
 			"erpnext.regional.create_transaction_log",
@@ -250,7 +253,11 @@
 		"on_trash": "erpnext.regional.check_deletion_permission"
 	},
 	"Purchase Invoice": {
-		"validate": "erpnext.regional.india.utils.update_grand_total_for_rcm"
+		"validate": [
+			"erpnext.regional.india.utils.update_grand_total_for_rcm",
+			"erpnext.regional.united_arab_emirates.utils.update_grand_total_for_rcm",
+			"erpnext.regional.united_arab_emirates.utils.validate_returns"
+			]
 	},
 	"Payment Entry": {
 		"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"],
@@ -307,6 +314,7 @@
 		"erpnext.projects.doctype.project.project.collect_project_status",
 		"erpnext.hr.doctype.shift_type.shift_type.process_auto_attendance_for_all_shifts",
 		"erpnext.support.doctype.issue.issue.set_service_level_agreement_variance",
+		"erpnext.erpnext_integrations.connectors.shopify_connection.sync_old_orders",
 	],
 	"daily": [
 		"erpnext.stock.reorder_item.reorder_item",
@@ -339,14 +347,16 @@
 		"erpnext.setup.doctype.email_digest.email_digest.send",
 		"erpnext.manufacturing.doctype.bom_update_tool.bom_update_tool.update_latest_price_in_all_boms",
 		"erpnext.hr.doctype.leave_ledger_entry.leave_ledger_entry.process_expired_allocation",
+		"erpnext.hr.doctype.leave_policy_assignment.leave_policy_assignment.automatically_allocate_leaves_based_on_leave_policy",
 		"erpnext.hr.utils.generate_leave_encashment",
+		"erpnext.hr.utils.allocate_earned_leaves",
+		"erpnext.hr.utils.grant_leaves_automatically",
 		"erpnext.loan_management.doctype.loan_security_shortfall.loan_security_shortfall.create_process_loan_security_shortfall",
 		"erpnext.loan_management.doctype.loan_interest_accrual.loan_interest_accrual.process_loan_interest_accrual_for_term_loans",
 		"erpnext.crm.doctype.lead.lead.daily_open_lead"
 	],
 	"monthly_long": [
 		"erpnext.accounts.deferred_revenue.process_deferred_accounting",
-		"erpnext.hr.utils.allocate_earned_leaves",
 		"erpnext.loan_management.doctype.loan_interest_accrual.loan_interest_accrual.process_loan_interest_accrual_for_demand_loans"
 	]
 }
@@ -390,7 +400,8 @@
 		'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'
+		'erpnext.controllers.taxes_and_totals.update_itemised_tax_data': 'erpnext.regional.united_arab_emirates.utils.update_itemised_tax_data',
+		'erpnext.accounts.doctype.purchase_invoice.purchase_invoice.make_regional_gl_entries': 'erpnext.regional.united_arab_emirates.utils.make_regional_gl_entries',
 	},
 	'Saudi Arabia': {
 		'erpnext.controllers.taxes_and_totals.update_itemised_tax_data': 'erpnext.regional.united_arab_emirates.utils.update_itemised_tax_data'
diff --git a/erpnext/hr/doctype/department_approver/department_approver.py b/erpnext/hr/doctype/department_approver/department_approver.py
index 9b2de0e..d337959 100644
--- a/erpnext/hr/doctype/department_approver/department_approver.py
+++ b/erpnext/hr/doctype/department_approver/department_approver.py
@@ -20,7 +20,7 @@
 	approvers = []
 	department_details = {}
 	department_list = []
-	employee = frappe.get_value("Employee", filters.get("employee"), ["department", "leave_approver", "expense_approver", "shift_request_approver"], as_dict=True)
+	employee = frappe.get_value("Employee", filters.get("employee"), ["employee_name","department", "leave_approver", "expense_approver", "shift_request_approver"], as_dict=True)
 
 	employee_department = filters.get("department") or employee.department
 	if employee_department:
@@ -59,11 +59,9 @@
 				and approver.approver=user.name""",(d, "%" + txt + "%", parentfield), as_list=True)
 
 	if len(approvers) == 0:
-		frappe.throw(_("Please set {0} for the Employee or for Department: {1}").
-			format(
-				field_name, frappe.bold(employee_department),
-				frappe.bold(employee.name)
-			),
-			title=_(field_name + " Missing"))
+		error_msg = _("Please set {0} for the Employee: {1}").format(field_name, frappe.bold(employee.employee_name))
+		if department_list:
+			error_msg += _(" or for Department: {0}").format(frappe.bold(employee_department))
+		frappe.throw(error_msg, title=_(field_name + " Missing"))
 
 	return set(tuple(approver) for approver in approvers)
diff --git a/erpnext/hr/doctype/employee/employee.json b/erpnext/hr/doctype/employee/employee.json
index da78919..4f1c04f 100644
--- a/erpnext/hr/doctype/employee/employee.json
+++ b/erpnext/hr/doctype/employee/employee.json
@@ -57,7 +57,6 @@
   "column_break_45",
   "shift_request_approver",
   "attendance_and_leave_details",
-  "leave_policy",
   "attendance_device_id",
   "column_break_44",
   "holiday_list",
@@ -412,14 +411,6 @@
    "options": "Branch"
   },
   {
-   "fetch_from": "grade.default_leave_policy",
-   "fetch_if_empty": 1,
-   "fieldname": "leave_policy",
-   "fieldtype": "Link",
-   "label": "Leave Policy",
-   "options": "Leave Policy"
-  },
-  {
    "description": "Applicable Holiday List",
    "fieldname": "holiday_list",
    "fieldtype": "Link",
@@ -672,10 +663,10 @@
    "oldfieldtype": "Date"
   },
   {
-   "depends_on": "eval:doc.status == \"Left\"",
    "fieldname": "relieving_date",
    "fieldtype": "Date",
    "label": "Relieving Date",
+   "mandatory_depends_on": "eval:doc.status == \"Left\"",
    "oldfieldname": "relieving_date",
    "oldfieldtype": "Date"
   },
@@ -822,7 +813,7 @@
  "idx": 24,
  "image_field": "image",
  "links": [],
- "modified": "2020-10-06 15:58:23.805489",
+ "modified": "2020-10-16 15:02:04.283657",
  "modified_by": "Administrator",
  "module": "HR",
  "name": "Employee",
diff --git a/erpnext/hr/doctype/employee_grade/employee_grade.json b/erpnext/hr/doctype/employee_grade/employee_grade.json
index e63ffae..88b061a 100644
--- a/erpnext/hr/doctype/employee_grade/employee_grade.json
+++ b/erpnext/hr/doctype/employee_grade/employee_grade.json
@@ -1,167 +1,69 @@
 {
- "allow_copy": 0, 
- "allow_guest_to_view": 0, 
- "allow_import": 1, 
- "allow_rename": 1, 
- "autoname": "Prompt", 
- "beta": 0, 
- "creation": "2018-04-13 16:14:24.174138", 
- "custom": 0, 
- "docstatus": 0, 
- "doctype": "DocType", 
- "document_type": "", 
- "editable_grid": 1, 
- "engine": "InnoDB", 
+ "actions": [],
+ "allow_import": 1,
+ "allow_rename": 1,
+ "autoname": "Prompt",
+ "creation": "2018-04-13 16:14:24.174138",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "default_salary_structure"
+ ],
  "fields": [
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0,
-   "allow_on_submit": 0,
-   "bold": 0,
-   "collapsible": 0,
-   "columns": 0,
-   "fieldname": "default_leave_policy",
-   "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": "Default Leave Policy",
-   "length": 0,
-   "no_copy": 0,
-   "options": "Leave Policy",
-   "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": "default_salary_structure",
    "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": "Default Salary Structure",
-   "length": 0,
-   "no_copy": 0,
-   "options": "Salary Structure",
-   "permlevel": 0,
-   "precision": "",
-   "print_hide": 0,
-   "print_hide_if_no_value": 0,
-   "read_only": 0,
-   "remember_last_selected_value": 0,
-   "report_hide": 0,
-   "reqd": 0,
-   "search_index": 0,
-   "set_only_once": 0,
-   "translatable": 0,
-   "unique": 0
+   "options": "Salary Structure"
   }
  ],
- "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-09-18 17:17:45.617624",
+ "index_web_pages_for_search": 1,
+ "links": [],
+ "modified": "2020-08-26 13:12:07.815330",
  "modified_by": "Administrator",
  "module": "HR",
  "name": "Employee Grade",
- "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": "HR 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": "HR User",
-   "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
+ "track_changes": 1
 }
\ No newline at end of file
diff --git a/erpnext/hr/doctype/hr_settings/hr_settings.json b/erpnext/hr/doctype/hr_settings/hr_settings.json
index 4374d29..f999635 100644
--- a/erpnext/hr/doctype/hr_settings/hr_settings.json
+++ b/erpnext/hr/doctype/hr_settings/hr_settings.json
@@ -21,6 +21,7 @@
   "show_leaves_of_all_department_members_in_calendar",
   "auto_leave_encashment",
   "restrict_backdated_leave_application",
+  "automatically_allocate_leaves_based_on_leave_policy",
   "hiring_settings",
   "check_vacancies"
  ],
@@ -41,7 +42,7 @@
    "description": "Employee records are created using the selected field",
    "fieldname": "emp_created_by",
    "fieldtype": "Select",
-   "label": "Employee Records to Be Created By",
+   "label": "Employee Records to be created by",
    "options": "Naming Series\nEmployee Number\nFull Name"
   },
   {
@@ -117,7 +118,7 @@
    "default": "0",
    "fieldname": "restrict_backdated_leave_application",
    "fieldtype": "Check",
-   "label": "Restrict Backdated Leave Applications"
+   "label": "Restrict Backdated Leave Application"
   },
   {
    "depends_on": "eval:doc.restrict_backdated_leave_application == 1",
@@ -125,13 +126,19 @@
    "fieldtype": "Link",
    "label": "Role Allowed to Create Backdated Leave Application",
    "options": "Role"
+  },
+  {
+   "default": "0",
+   "fieldname": "automatically_allocate_leaves_based_on_leave_policy",
+   "fieldtype": "Check",
+   "label": "Automatically Allocate Leaves Based On Leave Policy"
   }
  ],
  "icon": "fa fa-cog",
  "idx": 1,
  "issingle": 1,
  "links": [],
- "modified": "2020-10-13 11:49:46.168027",
+ "modified": "2020-08-27 14:30:28.995324",
  "modified_by": "Administrator",
  "module": "HR",
  "name": "HR Settings",
diff --git a/erpnext/hr/doctype/leave_allocation/leave_allocation.json b/erpnext/hr/doctype/leave_allocation/leave_allocation.json
index 007497e..4b31501 100644
--- a/erpnext/hr/doctype/leave_allocation/leave_allocation.json
+++ b/erpnext/hr/doctype/leave_allocation/leave_allocation.json
@@ -1,4 +1,5 @@
 {
+ "actions": [],
  "allow_import": 1,
  "autoname": "naming_series:",
  "creation": "2013-02-20 19:10:38",
@@ -24,6 +25,7 @@
   "compensatory_request",
   "leave_period",
   "leave_policy",
+  "leave_policy_assignment",
   "carry_forwarded_leaves_count",
   "expired",
   "amended_from",
@@ -160,9 +162,10 @@
    "read_only": 1
   },
   {
-   "fetch_from": "employee.leave_policy",
+   "fetch_from": "leave_policy_assignment.leave_policy",
    "fieldname": "leave_policy",
    "fieldtype": "Link",
+   "hidden": 1,
    "in_standard_filter": 1,
    "label": "Leave Policy",
    "options": "Leave Policy",
@@ -209,12 +212,21 @@
    "fieldtype": "Float",
    "label": "Carry Forwarded Leaves",
    "read_only": 1
+  },
+  {
+   "fieldname": "leave_policy_assignment",
+   "fieldtype": "Link",
+   "label": "Leave Policy Assignment",
+   "options": "Leave Policy Assignment",
+   "read_only": 1
   }
  ],
  "icon": "fa fa-ok",
  "idx": 1,
+ "index_web_pages_for_search": 1,
  "is_submittable": 1,
- "modified": "2019-08-08 15:08:42.440909",
+ "links": [],
+ "modified": "2020-08-20 14:25:10.314323",
  "modified_by": "Administrator",
  "module": "HR",
  "name": "Leave Allocation",
diff --git a/erpnext/hr/doctype/leave_allocation/leave_allocation.py b/erpnext/hr/doctype/leave_allocation/leave_allocation.py
index 03fe3fa..a09cd2e 100755
--- a/erpnext/hr/doctype/leave_allocation/leave_allocation.py
+++ b/erpnext/hr/doctype/leave_allocation/leave_allocation.py
@@ -51,9 +51,19 @@
 
 	def on_cancel(self):
 		self.create_leave_ledger_entry(submit=False)
+		if self.leave_policy_assignment:
+			self.update_leave_policy_assignments_when_no_allocations_left()
 		if self.carry_forward:
 			self.set_carry_forwarded_leaves_in_previous_allocation(on_cancel=True)
 
+	def update_leave_policy_assignments_when_no_allocations_left(self):
+		allocations = frappe.db.get_list("Leave Allocation", filters = {
+			"docstatus": 1,
+			"leave_policy_assignment": self.leave_policy_assignment
+		})
+		if len(allocations) == 0:
+			frappe.db.set_value("Leave Policy Assignment", self.leave_policy_assignment ,"leaves_allocated", 0)
+
 	def validate_period(self):
 		if date_diff(self.to_date, self.from_date) <= 0:
 			frappe.throw(_("To date cannot be before from date"))
diff --git a/erpnext/hr/doctype/leave_application/leave_application.py b/erpnext/hr/doctype/leave_application/leave_application.py
index 3f25f58..ca79dff 100755
--- a/erpnext/hr/doctype/leave_application/leave_application.py
+++ b/erpnext/hr/doctype/leave_application/leave_application.py
@@ -130,8 +130,7 @@
 		if self.status == "Approved":
 			for dt in daterange(getdate(self.from_date), getdate(self.to_date)):
 				date = dt.strftime("%Y-%m-%d")
-				status = "Half Day" if getdate(date) == getdate(self.half_day_date) else "On Leave"
-
+				status = "Half Day" if self.half_day_date and getdate(date) == getdate(self.half_day_date) else "On Leave"
 				attendance_name = frappe.db.exists('Attendance', dict(employee = self.employee,
 					attendance_date = date, docstatus = ('!=', 2)))
 
@@ -293,7 +292,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:
+
+		if self.half_day == 0:
 			self.half_day_date = None
 
 	def notify_employee(self):
diff --git a/erpnext/hr/doctype/leave_application/test_leave_application.py b/erpnext/hr/doctype/leave_application/test_leave_application.py
index 6e909c3..53b7a39 100644
--- a/erpnext/hr/doctype/leave_application/test_leave_application.py
+++ b/erpnext/hr/doctype/leave_application/test_leave_application.py
@@ -10,6 +10,7 @@
 from frappe.utils import add_days, nowdate, now_datetime, getdate, add_months
 from erpnext.hr.doctype.leave_type.test_leave_type import create_leave_type
 from erpnext.hr.doctype.leave_allocation.test_leave_allocation import create_leave_allocation
+from erpnext.hr.doctype.leave_policy_assignment.leave_policy_assignment import create_assignment_for_multiple_employees
 
 test_dependencies = ["Leave Allocation", "Leave Block List"]
 
@@ -410,25 +411,39 @@
 		self.assertEqual(get_leave_balance_on(employee.name, leave_type.name, nowdate(), add_days(nowdate(), 8)), 21)
 
 	def test_earned_leaves_creation(self):
+
+		frappe.db.sql('''delete from `tabLeave Period`''')
+		frappe.db.sql('''delete from `tabLeave Policy Assignment`''')
+		frappe.db.sql('''delete from `tabLeave Allocation`''')
+		frappe.db.sql('''delete from `tabLeave Ledger Entry`''')
+
 		leave_period = get_leave_period()
 		employee = get_employee()
 		leave_type = 'Test Earned Leave Type'
-		if not frappe.db.exists('Leave Type', leave_type):
-			frappe.get_doc(dict(
-				leave_type_name = leave_type,
-				doctype = 'Leave Type',
-				is_earned_leave = 1,
-				earned_leave_frequency = 'Monthly',
-				rounding = 0.5,
-				max_leaves_allowed = 6
-			)).insert()
+		frappe.delete_doc_if_exists("Leave Type", 'Test Earned Leave Type', force=1)
+		frappe.get_doc(dict(
+			leave_type_name = leave_type,
+			doctype = 'Leave Type',
+			is_earned_leave = 1,
+			earned_leave_frequency = 'Monthly',
+			rounding = 0.5,
+			max_leaves_allowed = 6
+		)).insert()
+
 		leave_policy = frappe.get_doc({
 			"doctype": "Leave Policy",
 			"leave_policy_details": [{"leave_type": leave_type, "annual_allocation": 6}]
 		}).insert()
-		frappe.db.set_value("Employee", employee.name, "leave_policy", leave_policy.name)
 
-		allocate_leaves(employee, leave_period, leave_type, 0, eligible_leaves = 12)
+		data = {
+			"assignment_based_on": "Leave Period",
+			"leave_policy": leave_policy.name,
+			"leave_period": leave_period.name
+		}
+
+		leave_policy_assignments = create_assignment_for_multiple_employees([employee.name], frappe._dict(data))
+
+		frappe.get_doc("Leave Policy Assignment", leave_policy_assignments[0]).grant_leave_alloc_for_employee()
 
 		from erpnext.hr.utils import allocate_earned_leaves
 		i = 0
diff --git a/erpnext/hr/doctype/leave_encashment/leave_encashment.py b/erpnext/hr/doctype/leave_encashment/leave_encashment.py
index 8913c64..c1dcc97 100644
--- a/erpnext/hr/doctype/leave_encashment/leave_encashment.py
+++ b/erpnext/hr/doctype/leave_encashment/leave_encashment.py
@@ -32,7 +32,7 @@
 		additional_salary.employee = self.employee
 		earning_component = frappe.get_value("Leave Type", self.leave_type, "earning_component")
 		if not earning_component:
-			frappe.throw(_("Please set Earning Component for Leave type: {0}.".format(self.leave_type)))
+			frappe.throw(_("Please set Earning Component for Leave type: {0}.").format(self.leave_type))
 		additional_salary.salary_component = earning_component
 		additional_salary.payroll_date = self.encashment_date
 		additional_salary.amount = self.encashment_amount
@@ -98,7 +98,11 @@
 		create_leave_ledger_entry(self, args, submit)
 
 		# create reverse entry for expired leaves
-		to_date = self.get_leave_allocation().get('to_date')
+		leave_allocation = self.get_leave_allocation()
+		if not leave_allocation:
+			return
+
+		to_date = leave_allocation.get('to_date')
 		if to_date < getdate(nowdate()):
 			args = frappe._dict(
 				leaves=self.encashable_days,
diff --git a/erpnext/hr/doctype/leave_encashment/test_leave_encashment.py b/erpnext/hr/doctype/leave_encashment/test_leave_encashment.py
index 99f6463..bbee18b 100644
--- a/erpnext/hr/doctype/leave_encashment/test_leave_encashment.py
+++ b/erpnext/hr/doctype/leave_encashment/test_leave_encashment.py
@@ -9,6 +9,7 @@
 from erpnext.hr.doctype.employee.test_employee import make_employee
 from erpnext.payroll.doctype.salary_structure.test_salary_structure import make_salary_structure
 from erpnext.hr.doctype.leave_period.test_leave_period import create_leave_period
+from erpnext.hr.doctype.leave_policy_assignment.leave_policy_assignment import create_assignment_for_multiple_employees
 from erpnext.hr.doctype.leave_policy.test_leave_policy import create_leave_policy\
 
 test_dependencies = ["Leave Type"]
@@ -16,6 +17,7 @@
 class TestLeaveEncashment(unittest.TestCase):
 	def setUp(self):
 		frappe.db.sql('''delete from `tabLeave Period`''')
+		frappe.db.sql('''delete from `tabLeave Policy Assignment`''')
 		frappe.db.sql('''delete from `tabLeave Allocation`''')
 		frappe.db.sql('''delete from `tabLeave Ledger Entry`''')
 		frappe.db.sql('''delete from `tabAdditional Salary`''')
@@ -29,14 +31,22 @@
 		# create employee, salary structure and assignment
 		self.employee = make_employee("test_employee_encashment@example.com")
 
-		frappe.db.set_value("Employee", self.employee, "leave_policy", leave_policy.name)
+		self.leave_period = create_leave_period(add_months(today(), -3), add_months(today(), 3))
+
+		data = {
+			"assignment_based_on": "Leave Period",
+			"leave_policy": leave_policy.name,
+			"leave_period": self.leave_period.name
+		}
+
+		leave_policy_assignments = create_assignment_for_multiple_employees([self.employee], frappe._dict(data))
 
 		salary_structure = make_salary_structure("Salary Structure for Encashment", "Monthly", self.employee,
 			other_details={"leave_encashment_amount_per_day": 50})
 
-		# create the leave period and assign the leaves
-		self.leave_period = create_leave_period(add_months(today(), -3), add_months(today(), 3))
-		self.leave_period.grant_leave_allocation(employee=self.employee)
+		#grant Leaves
+		frappe.get_doc("Leave Policy Assignment", leave_policy_assignments[0]).grant_leave_alloc_for_employee()
+
 
 	def test_leave_balance_value_and_amount(self):
 		frappe.db.sql('''delete from `tabLeave Encashment`''')
diff --git a/erpnext/hr/doctype/leave_period/leave_period.js b/erpnext/hr/doctype/leave_period/leave_period.js
index bad2b87..0e88bc1 100644
--- a/erpnext/hr/doctype/leave_period/leave_period.js
+++ b/erpnext/hr/doctype/leave_period/leave_period.js
@@ -2,14 +2,6 @@
 // For license information, please see license.txt
 
 frappe.ui.form.on('Leave Period', {
-	refresh: (frm)=>{
-		frm.set_df_property("grant_leaves", "hidden", frm.doc.__islocal ? 1:0);
-		if(!frm.is_new()) {
-			frm.add_custom_button(__('Grant Leaves'), function () {
-				frm.trigger("grant_leaves");
-			});
-		}
-	},
 	from_date: (frm)=>{
 		if (frm.doc.from_date && !frm.doc.to_date) {
 			var a_year_from_start = frappe.datetime.add_months(frm.doc.from_date, 12);
@@ -22,73 +14,7 @@
 				"filters": {
 					"company": frm.doc.company,
 				}
-			}
-		})
-	},
-	grant_leaves: function(frm) {
-		var d = new frappe.ui.Dialog({
-			title: __('Grant Leaves'),
-			fields: [
-				{
-					"label": "Filter Employees By (Optional)",
-					"fieldname": "sec_break",
-					"fieldtype": "Section Break",
-				},
-				{
-					"label": "Employee Grade",
-					"fieldname": "grade",
-					"fieldtype": "Link",
-					"options": "Employee Grade"
-				},
-				{
-					"label": "Department",
-					"fieldname": "department",
-					"fieldtype": "Link",
-					"options": "Department"
-				},
-				{
-					"fieldname": "col_break",
-					"fieldtype": "Column Break",
-				},
-				{
-					"label": "Designation",
-					"fieldname": "designation",
-					"fieldtype": "Link",
-					"options": "Designation"
-				},
-				{
-					"label": "Employee",
-					"fieldname": "employee",
-					"fieldtype": "Link",
-					"options": "Employee"
-				},
-				{
-					"fieldname": "sec_break",
-					"fieldtype": "Section Break",
-				},
-				{
-					"label": "Add unused leaves from previous allocations",
-					"fieldname": "carry_forward",
-					"fieldtype": "Check"
-				}
-			],
-			primary_action: function() {
-				var data = d.get_values();
-
-				frappe.call({
-					doc: frm.doc,
-					method: "grant_leave_allocation",
-					args: data,
-					callback: function(r) {
-						if(!r.exc) {
-							d.hide();
-							frm.reload_doc();
-						}
-					}
-				});
-			},
-			primary_action_label: __('Grant')
+			};
 		});
-		d.show();
-	}
+	},
 });
diff --git a/erpnext/hr/doctype/leave_period/leave_period.py b/erpnext/hr/doctype/leave_period/leave_period.py
index 0973ac7..28a33f6 100644
--- a/erpnext/hr/doctype/leave_period/leave_period.py
+++ b/erpnext/hr/doctype/leave_period/leave_period.py
@@ -7,24 +7,10 @@
 from frappe import _
 from frappe.utils import getdate, cstr, add_days, date_diff, getdate, ceil
 from frappe.model.document import Document
-from erpnext.hr.utils import validate_overlap, get_employee_leave_policy
+from erpnext.hr.utils import validate_overlap
 from frappe.utils.background_jobs import enqueue
-from six import iteritems
 
 class LeavePeriod(Document):
-	def get_employees(self, args):
-		conditions, values = [], []
-		for field, value in iteritems(args):
-			if value:
-				conditions.append("{0}=%s".format(field))
-				values.append(value)
-
-		condition_str = " and " + " and ".join(conditions) if len(conditions) else ""
-
-		employees = frappe._dict(frappe.db.sql("select name, date_of_joining from tabEmployee where status='Active' {condition}" #nosec
-			.format(condition=condition_str), tuple(values)))
-
-		return employees
 
 	def validate(self):
 		self.validate_dates()
@@ -33,96 +19,3 @@
 	def validate_dates(self):
 		if getdate(self.from_date) >= getdate(self.to_date):
 			frappe.throw(_("To date can not be equal or less than from date"))
-
-
-	def grant_leave_allocation(self, grade=None, department=None, designation=None,
-			employee=None, carry_forward=0):
-		employee_records = self.get_employees({
-			"grade": grade,
-			"department": department,
-			"designation": designation,
-			"name": employee
-		})
-
-		if employee_records:
-			if len(employee_records) > 20:
-				frappe.enqueue(grant_leave_alloc_for_employees, timeout=600,
-					employee_records=employee_records, leave_period=self, carry_forward=carry_forward)
-			else:
-				grant_leave_alloc_for_employees(employee_records, self, carry_forward)
-		else:
-			frappe.msgprint(_("No Employee Found"))
-
-def grant_leave_alloc_for_employees(employee_records, leave_period, carry_forward=0):
-	leave_allocations = []
-	existing_allocations_for = get_existing_allocations(list(employee_records.keys()), leave_period.name)
-	leave_type_details = get_leave_type_details()
-	count = 0
-	for employee in employee_records.keys():
-		if employee in existing_allocations_for:
-			continue
-		count +=1
-		leave_policy = get_employee_leave_policy(employee)
-		if leave_policy:
-			for leave_policy_detail in leave_policy.leave_policy_details:
-				if not leave_type_details.get(leave_policy_detail.leave_type).is_lwp:
-					leave_allocation = create_leave_allocation(employee, leave_policy_detail.leave_type,
-						leave_policy_detail.annual_allocation, leave_type_details, leave_period, carry_forward, employee_records.get(employee))
-					leave_allocations.append(leave_allocation)
-		frappe.db.commit()
-		frappe.publish_progress(count*100/len(set(employee_records.keys()) - set(existing_allocations_for)), title = _("Allocating leaves..."))
-
-	if leave_allocations:
-		frappe.msgprint(_("Leaves has been granted sucessfully"))
-
-def get_existing_allocations(employees, leave_period):
-	leave_allocations = frappe.db.sql_list("""
-		SELECT DISTINCT
-			employee
-		FROM `tabLeave Allocation`
-		WHERE
-			leave_period=%s
-			AND employee in (%s)
-			AND carry_forward=0
-			AND docstatus=1
-	""" % ('%s', ', '.join(['%s']*len(employees))), [leave_period] + employees)
-	if leave_allocations:
-		frappe.msgprint(_("Skipping Leave Allocation for the following employees, as Leave Allocation records already exists against them. {0}")
-			.format("\n".join(leave_allocations)))
-	return leave_allocations
-
-def get_leave_type_details():
-	leave_type_details = frappe._dict()
-	leave_types = frappe.get_all("Leave Type",
-		fields=["name", "is_lwp", "is_earned_leave", "is_compensatory", "is_carry_forward", "expire_carry_forwarded_leaves_after_days"])
-	for d in leave_types:
-		leave_type_details.setdefault(d.name, d)
-	return leave_type_details
-
-def create_leave_allocation(employee, leave_type, new_leaves_allocated, leave_type_details, leave_period, carry_forward, date_of_joining):
-	''' Creates leave allocation for the given employee in the provided leave period '''
-	if carry_forward and not leave_type_details.get(leave_type).is_carry_forward:
-		carry_forward = 0
-
-	# Calculate leaves at pro-rata basis for employees joining after the beginning of the given leave period
-	if getdate(date_of_joining) > getdate(leave_period.from_date):
-		remaining_period = ((date_diff(leave_period.to_date, date_of_joining) + 1) / (date_diff(leave_period.to_date, leave_period.from_date) + 1))
-		new_leaves_allocated = ceil(new_leaves_allocated * remaining_period)
-
-	# Earned Leaves and Compensatory Leaves are allocated by scheduler, initially allocate 0
-	if leave_type_details.get(leave_type).is_earned_leave == 1 or leave_type_details.get(leave_type).is_compensatory == 1:
-		new_leaves_allocated = 0
-
-	allocation = frappe.get_doc(dict(
-		doctype="Leave Allocation",
-		employee=employee,
-		leave_type=leave_type,
-		from_date=leave_period.from_date,
-		to_date=leave_period.to_date,
-		new_leaves_allocated=new_leaves_allocated,
-		leave_period=leave_period.name,
-		carry_forward=carry_forward
-		))
-	allocation.save(ignore_permissions = True)
-	allocation.submit()
-	return allocation.name
\ No newline at end of file
diff --git a/erpnext/hr/doctype/leave_period/test_leave_period.py b/erpnext/hr/doctype/leave_period/test_leave_period.py
index 1762cf9..b5857bc 100644
--- a/erpnext/hr/doctype/leave_period/test_leave_period.py
+++ b/erpnext/hr/doctype/leave_period/test_leave_period.py
@@ -5,43 +5,11 @@
 
 import frappe, erpnext
 import unittest
-from frappe.utils import today, add_months
-from erpnext.hr.doctype.employee.test_employee import make_employee
-from erpnext.hr.doctype.leave_application.leave_application import get_leave_balance_on
 
 test_dependencies = ["Employee", "Leave Type", "Leave Policy"]
 
 class TestLeavePeriod(unittest.TestCase):
-	def setUp(self):
-		frappe.db.sql("delete from `tabLeave Period`")
-
-	def test_leave_grant(self):
-		leave_type = "_Test Leave Type"
-
-		# create the leave policy
-		leave_policy = frappe.get_doc({
-			"doctype": "Leave Policy",
-			"leave_policy_details": [{
-				"leave_type": leave_type,
-				"annual_allocation": 20
-			}]
-		}).insert()
-		leave_policy.submit()
-
-		# create employee and assign the leave period
-		employee = "test_leave_period@employee.com"
-		employee_doc_name = make_employee(employee)
-		frappe.db.set_value("Employee", employee_doc_name, "leave_policy", leave_policy.name)
-
-		# clear the already allocated leave
-		frappe.db.sql('''delete from `tabLeave Allocation` where employee=%s''', "test_leave_period@employee.com")
-
-		# create the leave period
-		leave_period = create_leave_period(add_months(today(), -3), add_months(today(), 3))
-
-		# test leave_allocation
-		leave_period.grant_leave_allocation(employee=employee_doc_name)
-		self.assertEqual(get_leave_balance_on(employee_doc_name, leave_type, today()), 20)
+	pass
 
 def create_leave_period(from_date, to_date, company=None):
 	leave_period = frappe.db.get_value('Leave Period',
diff --git a/erpnext/hr/doctype/leave_policy_assignment/__init__.py b/erpnext/hr/doctype/leave_policy_assignment/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/hr/doctype/leave_policy_assignment/__init__.py
diff --git a/erpnext/hr/doctype/leave_policy_assignment/leave_policy_assignment.js b/erpnext/hr/doctype/leave_policy_assignment/leave_policy_assignment.js
new file mode 100644
index 0000000..7c32a0d
--- /dev/null
+++ b/erpnext/hr/doctype/leave_policy_assignment/leave_policy_assignment.js
@@ -0,0 +1,72 @@
+// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+frappe.ui.form.on('Leave Policy Assignment', {
+	onload: function(frm) {
+		frm.ignore_doctypes_on_cancel_all = ["Leave Ledger Entry"];
+	},
+
+	refresh: function(frm) {
+		if (frm.doc.docstatus === 1 && frm.doc.leaves_allocated === 0) {
+			frm.add_custom_button(__("Grant Leave"), function() {
+
+				frappe.call({
+					doc: frm.doc,
+					method: "grant_leave_alloc_for_employee",
+					callback: function(r) {
+						let leave_allocations = r.message;
+						let msg = frm.events.get_success_message(leave_allocations);
+						frappe.msgprint(msg);
+						cur_frm.refresh();
+					}
+				});
+			});
+		}
+	},
+
+	get_success_message: function(leave_allocations) {
+		let msg = __("Leaves has been granted successfully");
+		msg += "<br><table class='table table-bordered'>";
+		msg += "<tr><th>"+__('Leave Type')+"</th><th>"+__("Leave Allocation")+"</th><th>"+__("Leaves Granted")+"</th><tr>";
+		for (let key in leave_allocations) {
+			msg += "<tr><th>"+key+"</th><td>"+leave_allocations[key]["name"]+"</td><td>"+leave_allocations[key]["leaves"]+"</td></tr>";
+		}
+		msg += "</table>";
+		return msg;
+	},
+
+	assignment_based_on: function(frm) {
+		if (frm.doc.assignment_based_on) {
+			frm.events.set_effective_date(frm);
+		} else {
+			frm.set_value("effective_from", '');
+			frm.set_value("effective_to", '');
+		}
+	},
+
+	leave_period: function(frm) {
+		if (frm.doc.leave_period) {
+			frm.events.set_effective_date(frm);
+		}
+	},
+
+	set_effective_date: function(frm) {
+		if (frm.doc.assignment_based_on == "Leave Period" && frm.doc.leave_period) {
+			frappe.model.with_doc("Leave Period", frm.doc.leave_period, function () {
+				let from_date = frappe.model.get_value("Leave Period", frm.doc.leave_period, "from_date");
+				let to_date = frappe.model.get_value("Leave Period", frm.doc.leave_period, "to_date");
+				frm.set_value("effective_from", from_date);
+				frm.set_value("effective_to", to_date);
+
+			});
+		} else if (frm.doc.assignment_based_on == "Joining Date" && frm.doc.employee) {
+			frappe.model.with_doc("Employee", frm.doc.employee, function () {
+				let from_date = frappe.model.get_value("Employee", frm.doc.employee, "date_of_joining");
+				frm.set_value("effective_from", from_date);
+				frm.set_value("effective_to", frappe.datetime.add_months(frm.doc.effective_from, 12));
+			});
+		}
+		frm.refresh();
+	}
+
+});
diff --git a/erpnext/hr/doctype/leave_policy_assignment/leave_policy_assignment.json b/erpnext/hr/doctype/leave_policy_assignment/leave_policy_assignment.json
new file mode 100644
index 0000000..ecebb3b
--- /dev/null
+++ b/erpnext/hr/doctype/leave_policy_assignment/leave_policy_assignment.json
@@ -0,0 +1,160 @@
+{
+ "actions": [],
+ "autoname": "HR-LPOL-ASSGN-.#####",
+ "creation": "2020-08-19 13:02:43.343666",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "employee",
+  "employee_name",
+  "company",
+  "leave_policy",
+  "carry_forward",
+  "column_break_5",
+  "assignment_based_on",
+  "leave_period",
+  "effective_from",
+  "effective_to",
+  "leaves_allocated",
+  "amended_from"
+ ],
+ "fields": [
+  {
+   "fieldname": "employee",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "in_standard_filter": 1,
+   "label": "Employee",
+   "options": "Employee",
+   "reqd": 1
+  },
+  {
+   "fetch_from": "employee.employee_name",
+   "fieldname": "employee_name",
+   "fieldtype": "Data",
+   "label": "Employee name",
+   "read_only": 1
+  },
+  {
+   "fieldname": "leave_policy",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "in_standard_filter": 1,
+   "label": "Leave Policy",
+   "options": "Leave Policy",
+   "reqd": 1
+  },
+  {
+   "fieldname": "assignment_based_on",
+   "fieldtype": "Select",
+   "label": "Assignment based on",
+   "options": "\nLeave Period\nJoining Date"
+  },
+  {
+   "depends_on": "eval:doc.assignment_based_on == \"Leave Period\"",
+   "fieldname": "leave_period",
+   "fieldtype": "Link",
+   "label": "Leave Period",
+   "mandatory_depends_on": "eval:doc.assignment_based_on == \"Leave Period\"",
+   "options": "Leave Period"
+  },
+  {
+   "fieldname": "effective_from",
+   "fieldtype": "Date",
+   "label": "Effective From",
+   "read_only_depends_on": "eval:doc.assignment_based_on",
+   "reqd": 1
+  },
+  {
+   "fieldname": "effective_to",
+   "fieldtype": "Date",
+   "label": "Effective To",
+   "read_only_depends_on": "eval:doc.assignment_based_on == \"Leave Period\"",
+   "reqd": 1
+  },
+  {
+   "fetch_from": "employee.company",
+   "fieldname": "company",
+   "fieldtype": "Link",
+   "in_standard_filter": 1,
+   "label": "Company",
+   "options": "Company",
+   "read_only": 1
+  },
+  {
+   "fieldname": "column_break_5",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "amended_from",
+   "fieldtype": "Link",
+   "label": "Amended From",
+   "no_copy": 1,
+   "options": "Leave Policy Assignment",
+   "print_hide": 1,
+   "read_only": 1
+  },
+  {
+   "default": "0",
+   "fieldname": "carry_forward",
+   "fieldtype": "Check",
+   "label": "Add unused leaves from previous allocations"
+  },
+  {
+   "default": "0",
+   "fieldname": "leaves_allocated",
+   "fieldtype": "Check",
+   "hidden": 1,
+   "label": "Leaves Allocated"
+  }
+ ],
+ "is_submittable": 1,
+ "links": [],
+ "modified": "2020-10-15 15:18:15.227848",
+ "modified_by": "Administrator",
+ "module": "HR",
+ "name": "Leave Policy Assignment",
+ "owner": "Administrator",
+ "permissions": [
+  {
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "export": 1,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "HR Manager",
+   "share": 1,
+   "write": 1
+  },
+  {
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "export": 1,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "HR User",
+   "share": 1,
+   "write": 1
+  },
+  {
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "export": 1,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "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/hr/doctype/leave_policy_assignment/leave_policy_assignment.py b/erpnext/hr/doctype/leave_policy_assignment/leave_policy_assignment.py
new file mode 100644
index 0000000..a5068bc
--- /dev/null
+++ b/erpnext/hr/doctype/leave_policy_assignment/leave_policy_assignment.py
@@ -0,0 +1,163 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe.model.document import Document
+from frappe import _, bold
+from frappe.utils import getdate, date_diff, comma_and, formatdate
+from math import ceil
+import json
+from six import string_types
+
+class LeavePolicyAssignment(Document):
+
+	def validate(self):
+		self.validate_policy_assignment_overlap()
+		self.set_dates()
+
+	def set_dates(self):
+		if self.assignment_based_on == "Leave Period":
+			self.effective_from, self.effective_to = frappe.db.get_value("Leave Period", self.leave_period, ["from_date", "to_date"])
+		elif self.assignment_based_on == "Joining Date":
+			self.effective_from = frappe.db.get_value("Employee", self.employee, "date_of_joining")
+
+	def validate_policy_assignment_overlap(self):
+		leave_policy_assignments = frappe.get_all("Leave Policy Assignment", filters = {
+			"employee": self.employee,
+			"name": ("!=", self.name),
+			"docstatus": 1,
+			"effective_to": (">=", self.effective_from),
+			"effective_from": ("<=", self.effective_to)
+		})
+
+		if len(leave_policy_assignments):
+			frappe.throw(_("Leave Policy: {0} already assigned for Employee {1} for period {2} to {3}")
+				.format(bold(self.leave_policy), bold(self.employee), bold(formatdate(self.effective_from)), bold(formatdate(self.effective_to))))
+
+	def grant_leave_alloc_for_employee(self):
+		if self.leaves_allocated:
+			frappe.throw(_("Leave already have been assigned for this Leave Policy Assignment"))
+		else:
+			leave_allocations = {}
+			leave_type_details = get_leave_type_details()
+
+			leave_policy = frappe.get_doc("Leave Policy", self.leave_policy)
+			date_of_joining = frappe.db.get_value("Employee", self.employee, "date_of_joining")
+
+			for leave_policy_detail in leave_policy.leave_policy_details:
+				if not leave_type_details.get(leave_policy_detail.leave_type).is_lwp:
+					leave_allocation, new_leaves_allocated = self.create_leave_allocation(
+						leave_policy_detail.leave_type, leave_policy_detail.annual_allocation,
+						leave_type_details, date_of_joining
+					)
+
+				leave_allocations[leave_policy_detail.leave_type] = {"name": leave_allocation, "leaves": new_leaves_allocated}
+
+			self.db_set("leaves_allocated", 1)
+			return leave_allocations
+
+	def create_leave_allocation(self, leave_type, new_leaves_allocated, leave_type_details, date_of_joining):
+		# Creates leave allocation for the given employee in the provided leave period
+		carry_forward = self.carry_forward
+		if self.carry_forward and not leave_type_details.get(leave_type).is_carry_forward:
+			carry_forward = 0
+
+		new_leaves_allocated = self.get_new_leaves(leave_type, new_leaves_allocated,
+			leave_type_details, date_of_joining)
+
+		allocation = frappe.get_doc(dict(
+			doctype="Leave Allocation",
+			employee=self.employee,
+			leave_type=leave_type,
+			from_date=self.effective_from,
+			to_date=self.effective_to,
+			new_leaves_allocated=new_leaves_allocated,
+			leave_period=self.leave_period or None,
+			leave_policy_assignment = self.name,
+			leave_policy = self.leave_policy,
+			carry_forward=carry_forward
+			))
+		allocation.save(ignore_permissions = True)
+		allocation.submit()
+		return allocation.name, new_leaves_allocated
+
+	def get_new_leaves(self, leave_type, new_leaves_allocated, leave_type_details, date_of_joining):
+		# Calculate leaves at pro-rata basis for employees joining after the beginning of the given leave period
+		if getdate(date_of_joining) > getdate(self.effective_from):
+			remaining_period = ((date_diff(self.effective_to, date_of_joining) + 1) / (date_diff(self.effective_to, self.effective_from) + 1))
+			new_leaves_allocated = ceil(new_leaves_allocated * remaining_period)
+
+		# Earned Leaves and Compensatory Leaves are allocated by scheduler, initially allocate 0
+		if leave_type_details.get(leave_type).is_earned_leave == 1 or leave_type_details.get(leave_type).is_compensatory == 1:
+			new_leaves_allocated = 0
+
+		return new_leaves_allocated
+
+@frappe.whitelist()
+def grant_leave_for_multiple_employees(leave_policy_assignments):
+	leave_policy_assignments = json.loads(leave_policy_assignments)
+	not_granted = []
+	for assignment in leave_policy_assignments:
+		try:
+			frappe.get_doc("Leave Policy Assignment", assignment).grant_leave_alloc_for_employee()
+		except Exception:
+			not_granted.append(assignment)
+
+		if len(not_granted):
+			msg = _("Leave not Granted for Assignments:")+ bold(comma_and(not_granted)) + _(". Please Check documents")
+		else:
+			msg = _("Leave granted Successfully")
+	frappe.msgprint(msg)
+
+@frappe.whitelist()
+def create_assignment_for_multiple_employees(employees, data):
+
+	if isinstance(employees, string_types):
+		employees= json.loads(employees)
+
+	if isinstance(data, string_types):
+		data = frappe._dict(json.loads(data))
+
+	docs_name = []
+	for employee in employees:
+		assignment = frappe.new_doc("Leave Policy Assignment")
+		assignment.employee = employee
+		assignment.assignment_based_on = data.assignment_based_on or None
+		assignment.leave_policy = data.leave_policy
+		assignment.effective_from = getdate(data.effective_from) or None
+		assignment.effective_to = getdate(data.effective_to) or None
+		assignment.leave_period = data.leave_period or None
+		assignment.carry_forward = data.carry_forward
+
+		assignment.save()
+		assignment.submit()
+		docs_name.append(assignment.name)
+	return docs_name
+
+
+def automatically_allocate_leaves_based_on_leave_policy():
+	today = getdate()
+	automatically_allocate_leaves_based_on_leave_policy = frappe.db.get_single_value(
+		'HR Settings', 'automatically_allocate_leaves_based_on_leave_policy'
+	)
+
+	pending_assignments = frappe.get_list(
+		"Leave Policy Assignment",
+		filters = {"docstatus": 1, "leaves_allocated": 0, "effective_from": today}
+	)
+
+	if len(pending_assignments) and automatically_allocate_leaves_based_on_leave_policy:
+		for assignment in pending_assignments:
+			frappe.get_doc("Leave Policy Assignment", assignment.name).grant_leave_alloc_for_employee()
+
+
+def get_leave_type_details():
+	leave_type_details = frappe._dict()
+	leave_types = frappe.get_all("Leave Type",
+		fields=["name", "is_lwp", "is_earned_leave", "is_compensatory", "is_carry_forward", "expire_carry_forwarded_leaves_after_days"])
+	for d in leave_types:
+		leave_type_details.setdefault(d.name, d)
+	return leave_type_details
+
diff --git a/erpnext/hr/doctype/leave_policy_assignment/leave_policy_assignment_list.js b/erpnext/hr/doctype/leave_policy_assignment/leave_policy_assignment_list.js
new file mode 100644
index 0000000..468f243
--- /dev/null
+++ b/erpnext/hr/doctype/leave_policy_assignment/leave_policy_assignment_list.js
@@ -0,0 +1,138 @@
+frappe.listview_settings['Leave Policy Assignment'] = {
+	onload: function (list_view) {
+		let me = this;
+		list_view.page.add_inner_button(__("Bulk Leave Policy Assignment"), function () {
+			me.dialog = new frappe.ui.form.MultiSelectDialog({
+				doctype: "Employee",
+				target: cur_list,
+				setters: {
+					company: '',
+					department: '',
+				},
+				data_fields: [{
+					fieldname: 'leave_policy',
+					fieldtype: 'Link',
+					options: 'Leave Policy',
+					label: __('Leave Policy'),
+					reqd: 1
+				},
+				{
+					fieldname: 'assignment_based_on',
+					fieldtype: 'Select',
+					options: ["", "Leave Period"],
+					label: __('Assignment Based On'),
+					onchange: () => {
+						if (cur_dialog.fields_dict.assignment_based_on.value === "Leave Period") {
+							cur_dialog.set_df_property("effective_from", "read_only", 1);
+							cur_dialog.set_df_property("leave_period", "reqd", 1);
+							cur_dialog.set_df_property("effective_to", "read_only", 1);
+						} else {
+							cur_dialog.set_df_property("effective_from", "read_only", 0);
+							cur_dialog.set_df_property("leave_period", "reqd", 0);
+							cur_dialog.set_df_property("effective_to", "read_only", 0);
+							cur_dialog.set_value("effective_from", "");
+							cur_dialog.set_value("effective_to", "");
+						}
+					}
+				},
+				{
+					fieldname: "leave_period",
+					fieldtype: 'Link',
+					options: "Leave Period",
+					label: __('Leave Period'),
+					depends_on: doc => {
+						return doc.assignment_based_on == 'Leave Period';
+					},
+					onchange: () => {
+						if (cur_dialog.fields_dict.leave_period.value) {
+							me.set_effective_date();
+						}
+					}
+				},
+				{
+					fieldtype: "Column Break"
+				},
+				{
+					fieldname: 'effective_from',
+					fieldtype: 'Date',
+					label: __('Effective From'),
+					reqd: 1
+				},
+				{
+					fieldname: 'effective_to',
+					fieldtype: 'Date',
+					label: __('Effective To'),
+					reqd: 1
+				},
+				{
+					fieldname: 'carry_forward',
+					fieldtype: 'Check',
+					label: __('Add unused leaves from previous allocations')
+				}
+				],
+				get_query() {
+					return {
+						filters: {
+							status: ['=', 'Active']
+						}
+					};
+				},
+				add_filters_group: 1,
+				primary_action_label: "Assign",
+				action(employees, data) {
+					frappe.call({
+						method: 'erpnext.hr.doctype.leave_policy_assignment.leave_policy_assignment.create_assignment_for_multiple_employees',
+						async: false,
+						args: {
+							employees: employees,
+							data: data
+						}
+					});
+					cur_dialog.hide();
+				}
+			});
+		});
+
+		list_view.page.add_inner_button(__("Grant Leaves"), function () {
+			me.dialog = new frappe.ui.form.MultiSelectDialog({
+				doctype: "Leave Policy Assignment",
+				target: cur_list,
+				setters: {
+					company: '',
+					employee: '',
+				},
+				get_query() {
+					return {
+						filters: {
+							docstatus: ['=', 1],
+							leaves_allocated: ['=', 0]
+						}
+					};
+				},
+				add_filters_group: 1,
+				primary_action_label: "Grant Leaves",
+				action(leave_policy_assignments) {
+					frappe.call({
+						method: 'erpnext.hr.doctype.leave_policy_assignment.leave_policy_assignment.grant_leave_for_multiple_employees',
+						async: false,
+						args: {
+							leave_policy_assignments: leave_policy_assignments
+						}
+					});
+					me.dialog.hide();
+				}
+			});
+		});
+	},
+
+	set_effective_date: function () {
+		if (cur_dialog.fields_dict.assignment_based_on.value === "Leave Period" && cur_dialog.fields_dict.leave_period.value) {
+			frappe.model.with_doc("Leave Period", cur_dialog.fields_dict.leave_period.value, function () {
+				let from_date = frappe.model.get_value("Leave Period", cur_dialog.fields_dict.leave_period.value, "from_date");
+				let to_date = frappe.model.get_value("Leave Period", cur_dialog.fields_dict.leave_period.value, "to_date");
+				cur_dialog.set_value("effective_from", from_date);
+				cur_dialog.set_value("effective_to", to_date);
+			});
+		}
+	}
+};
\ No newline at end of file
diff --git a/erpnext/hr/doctype/leave_policy_assignment/test_leave_policy_assignment.py b/erpnext/hr/doctype/leave_policy_assignment/test_leave_policy_assignment.py
new file mode 100644
index 0000000..c7bc6fb
--- /dev/null
+++ b/erpnext/hr/doctype/leave_policy_assignment/test_leave_policy_assignment.py
@@ -0,0 +1,103 @@
+# -*- 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.hr.doctype.leave_application.test_leave_application import get_leave_period, get_employee
+from erpnext.hr.doctype.leave_policy_assignment.leave_policy_assignment import create_assignment_for_multiple_employees
+from erpnext.hr.doctype.leave_policy.test_leave_policy import create_leave_policy
+
+class TestLeavePolicyAssignment(unittest.TestCase):
+
+	def setUp(self):
+		for doctype in ["Leave Application", "Leave Allocation", "Leave Policy Assignment", "Leave Ledger Entry"]:
+			frappe.db.sql("delete from `tab{0}`".format(doctype)) #nosec
+
+	def test_grant_leaves(self):
+		leave_period = get_leave_period()
+		employee = get_employee()
+
+		# create the leave policy with leave type "_Test Leave Type", allocation = 10
+		leave_policy = create_leave_policy()
+		leave_policy.submit()
+
+
+		data = {
+			"assignment_based_on": "Leave Period",
+			"leave_policy": leave_policy.name,
+			"leave_period": leave_period.name
+		}
+
+		leave_policy_assignments = create_assignment_for_multiple_employees([employee.name], frappe._dict(data))
+
+		leave_policy_assignment_doc = frappe.get_doc("Leave Policy Assignment", leave_policy_assignments[0])
+		leave_policy_assignment_doc.grant_leave_alloc_for_employee()
+		leave_policy_assignment_doc.reload()
+
+		self.assertEqual(leave_policy_assignment_doc.leaves_allocated, 1)
+
+		leave_allocation = frappe.get_list("Leave Allocation", filters={
+			"employee": employee.name,
+			"leave_policy":leave_policy.name,
+			"leave_policy_assignment": leave_policy_assignments[0],
+			"docstatus": 1})[0]
+
+		leave_alloc_doc = frappe.get_doc("Leave Allocation", leave_allocation)
+
+		self.assertEqual(leave_alloc_doc.new_leaves_allocated, 10)
+		self.assertEqual(leave_alloc_doc.leave_type, "_Test Leave Type")
+		self.assertEqual(leave_alloc_doc.from_date, leave_period.from_date)
+		self.assertEqual(leave_alloc_doc.to_date, leave_period.to_date)
+		self.assertEqual(leave_alloc_doc.leave_policy, leave_policy.name)
+		self.assertEqual(leave_alloc_doc.leave_policy_assignment, leave_policy_assignments[0])
+
+	def test_allow_to_grant_all_leave_after_cancellation_of_every_leave_allocation(self):
+		leave_period = get_leave_period()
+		employee = get_employee()
+
+		# create the leave policy with leave type "_Test Leave Type", allocation = 10
+		leave_policy = create_leave_policy()
+		leave_policy.submit()
+
+
+		data = {
+			"assignment_based_on": "Leave Period",
+			"leave_policy": leave_policy.name,
+			"leave_period": leave_period.name
+		}
+
+		leave_policy_assignments = create_assignment_for_multiple_employees([employee.name], frappe._dict(data))
+
+		leave_policy_assignment_doc = frappe.get_doc("Leave Policy Assignment", leave_policy_assignments[0])
+		leave_policy_assignment_doc.grant_leave_alloc_for_employee()
+		leave_policy_assignment_doc.reload()
+
+
+		# every leave is allocated no more leave can be granted now
+		self.assertEqual(leave_policy_assignment_doc.leaves_allocated, 1)
+
+		leave_allocation = frappe.get_list("Leave Allocation", filters={
+			"employee": employee.name,
+			"leave_policy":leave_policy.name,
+			"leave_policy_assignment": leave_policy_assignments[0],
+			"docstatus": 1})[0]
+
+		leave_alloc_doc = frappe.get_doc("Leave Allocation", leave_allocation)
+
+		# User all allowed to grant leave when there is no allocation against assignment
+		leave_alloc_doc.cancel()
+		leave_alloc_doc.delete()
+
+		leave_policy_assignment_doc.reload()
+
+
+		# User are now allowed to grant leave
+		self.assertEqual(leave_policy_assignment_doc.leaves_allocated, 0)
+
+	def tearDown(self):
+		for doctype in ["Leave Application", "Leave Allocation", "Leave Policy Assignment", "Leave Ledger Entry"]:
+			frappe.db.sql("delete from `tab{0}`".format(doctype)) #nosec
+
+
diff --git a/erpnext/hr/doctype/leave_type/leave_type.json b/erpnext/hr/doctype/leave_type/leave_type.json
index 0af832f..a209291 100644
--- a/erpnext/hr/doctype/leave_type/leave_type.json
+++ b/erpnext/hr/doctype/leave_type/leave_type.json
@@ -15,6 +15,8 @@
   "column_break_3",
   "is_carry_forward",
   "is_lwp",
+  "is_ppl",
+  "fraction_of_daily_salary_per_leave",
   "is_optional_leave",
   "allow_negative",
   "include_holiday",
@@ -31,6 +33,7 @@
   "is_earned_leave",
   "earned_leave_frequency",
   "column_break_22",
+  "based_on_date_of_joining",
   "rounding"
  ],
  "fields": [
@@ -77,6 +80,7 @@
   },
   {
    "default": "0",
+   "depends_on": "eval:doc.is_ppl == 0",
    "fieldname": "is_lwp",
    "fieldtype": "Check",
    "label": "Is Leave Without Pay"
@@ -183,12 +187,33 @@
   {
    "fieldname": "column_break_22",
    "fieldtype": "Column Break"
+  },
+  {
+   "default": "0",
+   "depends_on": "eval:doc.is_earned_leave",
+   "description": "If checked, leave will be granted on the day of joining every month.",
+   "fieldname": "based_on_date_of_joining",
+   "fieldtype": "Check",
+   "label": "Based On Date Of Joining"
+  },
+  {
+   "depends_on": "eval:doc.is_lwp == 0",
+   "fieldname": "is_ppl",
+   "fieldtype": "Check",
+   "label": "Is Partially Paid Leave"
+  },
+  {
+   "depends_on": "eval:doc.is_ppl == 1",
+   "fieldname": "fraction_of_daily_salary_per_leave",
+   "fieldtype": "Float",
+   "label": "Fraction of Daily Salary per Leave",
+   "mandatory_depends_on": "eval:doc.is_ppl == 1"
   }
  ],
  "icon": "fa fa-flag",
  "idx": 1,
  "links": [],
- "modified": "2019-12-12 12:48:37.780254",
+ "modified": "2020-10-15 15:49:47.555105",
  "modified_by": "Administrator",
  "module": "HR",
  "name": "Leave Type",
diff --git a/erpnext/hr/doctype/leave_type/leave_type.py b/erpnext/hr/doctype/leave_type/leave_type.py
index c0d1296..21f180b 100644
--- a/erpnext/hr/doctype/leave_type/leave_type.py
+++ b/erpnext/hr/doctype/leave_type/leave_type.py
@@ -21,3 +21,9 @@
 			leave_allocation = [l['name'] for l in leave_allocation]
 			if leave_allocation:
 				frappe.throw(_('Leave application is linked with leave allocations {0}. Leave application cannot be set as leave without pay').format(", ".join(leave_allocation))) #nosec
+
+		if self.is_lwp and self.is_ppl:
+			frappe.throw(_("Leave Type can be either without pay or partial pay"))
+
+		if self.is_ppl and (self.fraction_of_daily_salary_per_leave < 0 or  self.fraction_of_daily_salary_per_leave > 1):
+			frappe.throw(_("The fraction of Daily Salary per Leave should be between 0 and 1"))
diff --git a/erpnext/hr/doctype/leave_type/test_leave_type.py b/erpnext/hr/doctype/leave_type/test_leave_type.py
index 0c4f435..7fef297 100644
--- a/erpnext/hr/doctype/leave_type/test_leave_type.py
+++ b/erpnext/hr/doctype/leave_type/test_leave_type.py
@@ -18,9 +18,14 @@
         "allow_encashment": args.allow_encashment or 0,
         "is_earned_leave": args.is_earned_leave or 0,
         "is_lwp": args.is_lwp or 0,
+        "is_ppl":args.is_ppl or 0,
         "is_carry_forward": args.is_carry_forward or 0,
         "expire_carry_forwarded_leaves_after_days": args.expire_carry_forwarded_leaves_after_days or 0,
         "encashment_threshold_days": args.encashment_threshold_days or 5,
         "earning_component": "Leave Encashment"
     })
+
+    if leave_type.is_ppl:
+        leave_type.fraction_of_daily_salary_per_leave = args.fraction_of_daily_salary_per_leave or 0.5
+
     return leave_type
\ No newline at end of file
diff --git a/erpnext/hr/doctype/upload_attendance/upload_attendance.js b/erpnext/hr/doctype/upload_attendance/upload_attendance.js
index 9df2948..29aa854 100644
--- a/erpnext/hr/doctype/upload_attendance/upload_attendance.js
+++ b/erpnext/hr/doctype/upload_attendance/upload_attendance.js
@@ -24,10 +24,10 @@
 		}
 		window.location.href = repl(frappe.request.url +
 			'?cmd=%(cmd)s&from_date=%(from_date)s&to_date=%(to_date)s', {
-				cmd: "erpnext.hr.doctype.upload_attendance.upload_attendance.get_template",
-				from_date: this.frm.doc.att_fr_date,
-				to_date: this.frm.doc.att_to_date,
-			});
+			cmd: "erpnext.hr.doctype.upload_attendance.upload_attendance.get_template",
+			from_date: this.frm.doc.att_fr_date,
+			to_date: this.frm.doc.att_to_date,
+		});
 	},
 
 	show_upload() {
diff --git a/erpnext/hr/doctype/upload_attendance/upload_attendance.py b/erpnext/hr/doctype/upload_attendance/upload_attendance.py
index edf05e8..674c8e3 100644
--- a/erpnext/hr/doctype/upload_attendance/upload_attendance.py
+++ b/erpnext/hr/doctype/upload_attendance/upload_attendance.py
@@ -28,7 +28,12 @@
 	w = UnicodeWriter()
 	w = add_header(w)
 
-	w = add_data(w, args)
+	try:
+		w = add_data(w, args)
+	except Exception as e:
+		frappe.clear_messages()
+		frappe.respond_as_web_page("Holiday List Missing", html=e)
+		return
 
 	# write out response as a type csv
 	frappe.response['result'] = cstr(w.getvalue())
diff --git a/erpnext/hr/utils.py b/erpnext/hr/utils.py
index 8d95924..d700e7f 100644
--- a/erpnext/hr/utils.py
+++ b/erpnext/hr/utils.py
@@ -215,19 +215,6 @@
 		+ _(") for {0}").format(exists_for)
 	frappe.throw(msg)
 
-def get_employee_leave_policy(employee):
-	leave_policy = frappe.db.get_value("Employee", employee, "leave_policy")
-	if not leave_policy:
-		employee_grade = frappe.db.get_value("Employee", employee, "grade")
-		if employee_grade:
-			leave_policy = frappe.db.get_value("Employee Grade", employee_grade, "default_leave_policy")
-			if not leave_policy:
-				frappe.throw(_("Employee {0} of grade {1} have no default leave policy").format(employee, employee_grade))
-	if leave_policy:
-		return frappe.get_doc("Leave Policy", leave_policy)
-	else:
-		frappe.throw(_("Please set leave policy for employee {0} in Employee / Grade record").format(employee))
-
 def validate_duplicate_exemption_for_payroll_period(doctype, docname, payroll_period, employee):
 	existing_record = frappe.db.exists(doctype, {
 		"payroll_period": payroll_period,
@@ -300,43 +287,68 @@
 
 def allocate_earned_leaves():
 	'''Allocate earned leaves to Employees'''
-	e_leave_types = frappe.get_all("Leave Type",
-		fields=["name", "max_leaves_allowed", "earned_leave_frequency", "rounding"],
-		filters={'is_earned_leave' : 1})
+	e_leave_types = get_earned_leaves()
 	today = getdate()
-	divide_by_frequency = {"Yearly": 1, "Half-Yearly": 6, "Quarterly": 4, "Monthly": 12}
 
 	for e_leave_type in e_leave_types:
-		leave_allocations = frappe.db.sql("""select name, employee, from_date, to_date from `tabLeave Allocation` where %s
-			between from_date and to_date and docstatus=1 and leave_type=%s""", (today, e_leave_type.name), as_dict=1)
+
+		leave_allocations = get_leave_allocations(today, e_leave_type.name)
+
 		for allocation in leave_allocations:
-			leave_policy = get_employee_leave_policy(allocation.employee)
-			if not leave_policy:
+
+			if not allocation.leave_policy_assignment and not allocation.leave_policy:
 				continue
-			if not e_leave_type.earned_leave_frequency == "Monthly":
-				if not check_frequency_hit(allocation.from_date, today, e_leave_type.earned_leave_frequency):
-					continue
+
+			leave_policy = allocation.leave_policy if allocation.leave_policy else frappe.db.get_value(
+					"Leave Policy Assignment", allocation.leave_policy_assignment, ["leave_policy"])
+
 			annual_allocation = frappe.db.get_value("Leave Policy Detail", filters={
-				'parent': leave_policy.name,
+				'parent': leave_policy,
 				'leave_type': e_leave_type.name
 			}, fieldname=['annual_allocation'])
-			if annual_allocation:
-				earned_leaves = flt(annual_allocation) / divide_by_frequency[e_leave_type.earned_leave_frequency]
-				if e_leave_type.rounding == "0.5":
-					earned_leaves = round(earned_leaves * 2) / 2
-				else:
-					earned_leaves = round(earned_leaves)
 
-				allocation = frappe.get_doc('Leave Allocation', allocation.name)
-				new_allocation = flt(allocation.total_leaves_allocated) + flt(earned_leaves)
+			from_date=allocation.from_date
 
-				if new_allocation > e_leave_type.max_leaves_allowed and e_leave_type.max_leaves_allowed > 0:
-					new_allocation = e_leave_type.max_leaves_allowed
+			if e_leave_type.based_on_date_of_joining_date:
+				from_date  = frappe.db.get_value("Employee", allocation.employee, "date_of_joining")
 
-				if new_allocation == allocation.total_leaves_allocated:
-					continue
-				allocation.db_set("total_leaves_allocated", new_allocation, update_modified=False)
-				create_additional_leave_ledger_entry(allocation, earned_leaves, today)
+			if check_effective_date(from_date, today, e_leave_type.earned_leave_frequency, e_leave_type.based_on_date_of_joining_date):
+				update_previous_leave_allocation(allocation, annual_allocation, e_leave_type)
+
+def update_previous_leave_allocation(allocation, annual_allocation, e_leave_type):
+	divide_by_frequency = {"Yearly": 1, "Half-Yearly": 6, "Quarterly": 4, "Monthly": 12}
+	if annual_allocation:
+		earned_leaves = flt(annual_allocation) / divide_by_frequency[e_leave_type.earned_leave_frequency]
+		if e_leave_type.rounding == "0.5":
+			earned_leaves = round(earned_leaves * 2) / 2
+		else:
+			earned_leaves = round(earned_leaves)
+
+		allocation = frappe.get_doc('Leave Allocation', allocation.name)
+		new_allocation = flt(allocation.total_leaves_allocated) + flt(earned_leaves)
+
+		if new_allocation > e_leave_type.max_leaves_allowed and e_leave_type.max_leaves_allowed > 0:
+			new_allocation = e_leave_type.max_leaves_allowed
+
+		if new_allocation != allocation.total_leaves_allocated:
+			allocation.db_set("total_leaves_allocated", new_allocation, update_modified=False)
+			today_date = today()
+			create_additional_leave_ledger_entry(allocation, earned_leaves, today_date)
+
+
+def get_leave_allocations(date, leave_type):
+	return frappe.db.sql("""select name, employee, from_date, to_date, leave_policy_assignment, leave_policy
+		from `tabLeave Allocation`
+		where
+			%s between from_date and to_date and docstatus=1
+			and leave_type=%s""",
+	(date, leave_type), as_dict=1)
+
+
+def get_earned_leaves():
+	return frappe.get_all("Leave Type",
+		fields=["name", "max_leaves_allowed", "earned_leave_frequency", "rounding", "based_on_date_of_joining"],
+		filters={'is_earned_leave' : 1})
 
 def create_additional_leave_ledger_entry(allocation, leaves, date):
 	''' Create leave ledger entry for leave types '''
@@ -345,24 +357,32 @@
 	allocation.unused_leaves = 0
 	allocation.create_leave_ledger_entry()
 
-def check_frequency_hit(from_date, to_date, frequency):
-	'''Return True if current date matches frequency'''
-	from_dt = get_datetime(from_date)
-	to_dt = get_datetime(to_date)
+def check_effective_date(from_date, to_date, frequency, based_on_date_of_joining_date):
+	import calendar
 	from dateutil import relativedelta
-	rd = relativedelta.relativedelta(to_dt, from_dt)
-	months = rd.months
-	if frequency == "Quarterly":
-		if not months % 3:
+
+	from_date = get_datetime(from_date)
+	to_date = get_datetime(to_date)
+	rd = relativedelta.relativedelta(to_date, from_date)
+	#last day of month
+	last_day =  calendar.monthrange(to_date.year, to_date.month)[1]
+
+	if (from_date.day == to_date.day and based_on_date_of_joining_date) or (not based_on_date_of_joining_date and to_date.day == last_day):
+		if frequency == "Monthly":
 			return True
-	elif frequency == "Half-Yearly":
-		if not months % 6:
+		elif frequency == "Quarterly" and rd.months % 3:
 			return True
-	elif frequency == "Yearly":
-		if not months % 12:
+		elif frequency == "Half-Yearly" and rd.months % 6:
 			return True
+		elif frequency == "Yearly" and rd.months % 12:
+			return True
+
+	if frappe.flags.in_test:
+		return True
+
 	return False
 
+
 def get_salary_assignment(employee, date):
 	assignment = frappe.db.sql("""
 		select * from `tabSalary Structure Assignment`
@@ -454,3 +474,10 @@
 	if sum_of_claimed_amount and flt(sum_of_claimed_amount[0].total_amount) > 0:
 		total_claimed_amount = sum_of_claimed_amount[0].total_amount
 	return total_claimed_amount
+
+def grant_leaves_automatically():
+	automatically_allocate_leaves_based_on_leave_policy = frappe.db.get_singles_value("HR Settings", "automatically_allocate_leaves_based_on_leave_policy")
+	if automatically_allocate_leaves_based_on_leave_policy:
+		lpa = frappe.db.get_all("Leave Policy Assignment", filters={"effective_from": getdate(), "docstatus": 1, "leaves_allocated":0})
+		for assignment in lpa:
+			frappe.get_doc("Leave Policy Assignment", assignment.name).grant_leave_alloc_for_employee()
diff --git a/erpnext/loan_management/desk_page/loan/loan.json b/erpnext/loan_management/desk_page/loan/loan.json
index 3bdd1ce..fc59c19 100644
--- a/erpnext/loan_management/desk_page/loan/loan.json
+++ b/erpnext/loan_management/desk_page/loan/loan.json
@@ -3,7 +3,7 @@
   {
    "hidden": 0,
    "label": "Loan",
-   "links": "[\n    {\n        \"description\": \"Loan Type for interest and penalty rates\",\n        \"label\": \"Loan Type\",\n        \"name\": \"Loan Type\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"description\": \"Loan Applications from customers and employees.\",\n        \"label\": \"Loan Application\",\n        \"name\": \"Loan Application\",\n        \"type\": \"doctype\"\n    },\n    {   \"dependencies\": [\n            \"Loan Type\"\n        ],\n        \"description\": \"Loans provided to customers and employees.\",\n        \"label\": \"Loan\",\n        \"name\": \"Loan\",\n        \"type\": \"doctype\"\n    }\n]"
+   "links": "[\n    {\n        \"description\": \"Loan Type for interest and penalty rates\",\n        \"label\": \"Loan Type\",\n        \"name\": \"Loan Type\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"description\": \"Loan Applications from customers and employees.\",\n        \"label\": \"Loan Application\",\n        \"name\": \"Loan Application\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"description\": \"Loans provided to customers and employees.\",\n        \"label\": \"Loan\",\n        \"name\": \"Loan\",\n        \"type\": \"doctype\"\n    }\n]"
   },
   {
    "hidden": 0,
@@ -13,7 +13,7 @@
   {
    "hidden": 0,
    "label": "Disbursement and Repayment",
-   "links": "[\n    {\n        \"label\": \"Loan Disbursement\",\n        \"name\": \"Loan Disbursement\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"Loan Repayment\",\n        \"name\": \"Loan Repayment\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"Loan Interest Accrual\",\n        \"name\": \"Loan Interest Accrual\",\n        \"type\": \"doctype\"\n    }\n]"
+   "links": "[\n    {\n        \"label\": \"Loan Disbursement\",\n        \"name\": \"Loan Disbursement\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"Loan Repayment\",\n        \"name\": \"Loan Repayment\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"Loan Write Off\",\n        \"name\": \"Loan Write Off\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"Loan Interest Accrual\",\n        \"name\": \"Loan Interest Accrual\",\n        \"type\": \"doctype\"\n    }\n]"
   },
   {
    "hidden": 0,
@@ -34,10 +34,11 @@
  "docstatus": 0,
  "doctype": "Desk Page",
  "extends_another_page": 0,
+ "hide_custom": 0,
  "idx": 0,
  "is_standard": 1,
  "label": "Loan",
- "modified": "2020-06-07 19:42:14.947902",
+ "modified": "2020-10-17 12:59:50.336085",
  "modified_by": "Administrator",
  "module": "Loan Management",
  "name": "Loan",
diff --git a/erpnext/loan_management/doctype/loan/loan.js b/erpnext/loan_management/doctype/loan/loan.js
index 9b4c217..28af3a9 100644
--- a/erpnext/loan_management/doctype/loan/loan.js
+++ b/erpnext/loan_management/doctype/loan/loan.js
@@ -7,10 +7,14 @@
 	setup: function(frm) {
 		frm.make_methods = {
 			'Loan Disbursement': function() { frm.trigger('make_loan_disbursement') },
-			'Loan Security Unpledge': function() { frm.trigger('create_loan_security_unpledge') }
+			'Loan Security Unpledge': function() { frm.trigger('create_loan_security_unpledge') },
+			'Loan Write Off': function() { frm.trigger('make_loan_write_off_entry') }
 		}
 	},
 	onload: function (frm) {
+		// Ignore loan security pledge on cancel of loan
+		frm.ignore_doctypes_on_cancel_all = ["Loan Security Pledge"];
+
 		frm.set_query("loan_application", function () {
 			return {
 				"filters": {
@@ -21,6 +25,14 @@
 			};
 		});
 
+		frm.set_query("loan_type", function () {
+			return {
+				"filters": {
+					"docstatus": 1
+				}
+			};
+		});
+
 		$.each(["penalty_income_account", "interest_income_account"], function(i, field) {
 			frm.set_query(field, function () {
 				return {
@@ -49,24 +61,33 @@
 
 	refresh: function (frm) {
 		if (frm.doc.docstatus == 1) {
-			if (frm.doc.status == "Sanctioned" || frm.doc.status == 'Partially Disbursed') {
+			if (["Disbursed", "Partially Disbursed"].includes(frm.doc.status) && (!frm.doc.repay_from_salary)) {
+				frm.add_custom_button(__('Request Loan Closure'), function() {
+					frm.trigger("request_loan_closure");
+				},__('Status'));
+
+				frm.add_custom_button(__('Loan Repayment'), function() {
+					frm.trigger("make_repayment_entry");
+				},__('Create'));
+			}
+
+			if (["Sanctioned", "Partially Disbursed"].includes(frm.doc.status)) {
 				frm.add_custom_button(__('Loan Disbursement'), function() {
 					frm.trigger("make_loan_disbursement");
 				},__('Create'));
 			}
 
-			if (["Disbursed", "Partially Disbursed"].includes(frm.doc.status) && (!frm.doc.repay_from_salary)) {
-				frm.add_custom_button(__('Loan Repayment'), function() {
-					frm.trigger("make_repayment_entry");
-				},__('Create'));
-
-			}
-
 			if (frm.doc.status == "Loan Closure Requested") {
 				frm.add_custom_button(__('Loan Security Unpledge'), function() {
 					frm.trigger("create_loan_security_unpledge");
 				},__('Create'));
 			}
+
+			if (["Loan Closure Requested", "Disbursed", "Partially Disbursed"].includes(frm.doc.status)) {
+				frm.add_custom_button(__('Loan Write Off'), function() {
+					frm.trigger("make_loan_write_off_entry");
+				},__('Create'));
+			}
 		}
 		frm.trigger("toggle_fields");
 	},
@@ -117,6 +138,38 @@
 		})
 	},
 
+	make_loan_write_off_entry: function(frm) {
+		frappe.call({
+			args: {
+				"loan": frm.doc.name,
+				"company": frm.doc.company,
+				"as_dict": 1
+			},
+			method: "erpnext.loan_management.doctype.loan.loan.make_loan_write_off",
+			callback: function (r) {
+				if (r.message)
+					var doc = frappe.model.sync(r.message)[0];
+				frappe.set_route("Form", doc.doctype, doc.name);
+			}
+		})
+	},
+
+	request_loan_closure: function(frm) {
+		frappe.confirm(__("Do you really want to close this loan"),
+			function() {
+				frappe.call({
+					args: {
+						'loan': frm.doc.name
+					},
+					method: "erpnext.loan_management.doctype.loan.loan.request_loan_closure",
+					callback: function() {
+						frm.reload_doc();
+					}
+				});
+			}
+		);
+	},
+
 	create_loan_security_unpledge: function(frm) {
 		frappe.call({
 			method: "erpnext.loan_management.doctype.loan.loan.unpledge_security",
diff --git a/erpnext/loan_management/doctype/loan/loan.json b/erpnext/loan_management/doctype/loan/loan.json
index aa5e21b..d468f52 100644
--- a/erpnext/loan_management/doctype/loan/loan.json
+++ b/erpnext/loan_management/doctype/loan/loan.json
@@ -43,6 +43,7 @@
   "section_break_17",
   "total_payment",
   "total_principal_paid",
+  "written_off_amount",
   "column_break_19",
   "total_interest_payable",
   "total_amount_paid",
@@ -75,6 +76,7 @@
    "fieldname": "loan_application",
    "fieldtype": "Link",
    "label": "Loan Application",
+   "no_copy": 1,
    "options": "Loan Application"
   },
   {
@@ -134,6 +136,7 @@
    "fieldname": "loan_amount",
    "fieldtype": "Currency",
    "label": "Loan Amount",
+   "non_negative": 1,
    "options": "Company:company:default_currency"
   },
   {
@@ -148,7 +151,8 @@
    "depends_on": "eval:doc.status==\"Disbursed\"",
    "fieldname": "disbursement_date",
    "fieldtype": "Date",
-   "label": "Disbursement Date"
+   "label": "Disbursement Date",
+   "no_copy": 1
   },
   {
    "depends_on": "is_term_loan",
@@ -252,6 +256,7 @@
    "fieldname": "total_payment",
    "fieldtype": "Currency",
    "label": "Total Payable Amount",
+   "no_copy": 1,
    "options": "Company:company:default_currency",
    "read_only": 1
   },
@@ -265,6 +270,7 @@
    "fieldname": "total_interest_payable",
    "fieldtype": "Currency",
    "label": "Total Interest Payable",
+   "no_copy": 1,
    "options": "Company:company:default_currency",
    "read_only": 1
   },
@@ -273,6 +279,7 @@
    "fieldname": "total_amount_paid",
    "fieldtype": "Currency",
    "label": "Total Amount Paid",
+   "no_copy": 1,
    "options": "Company:company:default_currency",
    "read_only": 1
   },
@@ -289,8 +296,7 @@
    "default": "0",
    "fieldname": "is_secured_loan",
    "fieldtype": "Check",
-   "label": "Is Secured Loan",
-   "read_only": 1
+   "label": "Is Secured Loan"
   },
   {
    "default": "0",
@@ -313,6 +319,7 @@
    "fieldname": "total_principal_paid",
    "fieldtype": "Currency",
    "label": "Total Principal Paid",
+   "no_copy": 1,
    "options": "Company:company:default_currency",
    "read_only": 1
   },
@@ -320,21 +327,33 @@
    "fieldname": "disbursed_amount",
    "fieldtype": "Currency",
    "label": "Disbursed Amount",
+   "no_copy": 1,
    "options": "Company:company:default_currency",
    "read_only": 1
   },
   {
+   "depends_on": "eval:doc.is_secured_loan",
    "fetch_from": "loan_application.maximum_loan_amount",
    "fieldname": "maximum_loan_amount",
    "fieldtype": "Currency",
    "label": "Maximum Loan Amount",
+   "no_copy": 1,
+   "options": "Company:company:default_currency",
+   "read_only": 1
+  },
+  {
+   "fieldname": "written_off_amount",
+   "fieldtype": "Currency",
+   "label": "Written Off Amount",
+   "no_copy": 1,
    "options": "Company:company:default_currency",
    "read_only": 1
   }
  ],
+ "index_web_pages_for_search": 1,
  "is_submittable": 1,
  "links": [],
- "modified": "2020-08-01 12:36:11.255233",
+ "modified": "2020-11-24 12:27:23.208240",
  "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 d1b7589..8405d6e 100644
--- a/erpnext/loan_management/doctype/loan/loan.py
+++ b/erpnext/loan_management/doctype/loan/loan.py
@@ -9,6 +9,7 @@
 from frappe.utils import flt, rounded, add_months, nowdate, getdate, now_datetime
 from erpnext.loan_management.doctype.loan_security_unpledge.loan_security_unpledge import get_pledged_security_qty
 from erpnext.controllers.accounts_controller import AccountsController
+from erpnext.loan_management.doctype.loan_repayment.loan_repayment import calculate_amounts
 
 class Loan(AccountsController):
 	def validate(self):
@@ -137,9 +138,12 @@
 				})
 
 	def unlink_loan_security_pledge(self):
-		frappe.db.sql("""UPDATE `tabLoan Security Pledge` SET
-			loan = '', status = 'Unpledged'
-			where name = %s """, (self.loan_security_pledge))
+		pledges = frappe.get_all('Loan Security Pledge', fields=['name'], filters={'loan': self.name})
+		pledge_list = [d.name for d in pledges]
+		if pledge_list:
+			frappe.db.sql("""UPDATE `tabLoan Security Pledge` SET
+				loan = '', status = 'Unpledged'
+				where name in (%s) """ % (', '.join(['%s']*len(pledge_list))), tuple(pledge_list)) #nosec
 
 def update_total_amount_paid(doc):
 	total_amount_paid = 0
@@ -183,6 +187,24 @@
 	return monthly_repayment_amount
 
 @frappe.whitelist()
+def request_loan_closure(loan, posting_date=None):
+	if not posting_date:
+		posting_date = getdate()
+
+	amounts = calculate_amounts(loan, posting_date)
+	pending_amount = amounts['payable_amount'] + amounts['unaccrued_interest']
+
+	loan_type = frappe.get_value('Loan', loan, 'loan_type')
+	write_off_limit = frappe.get_value('Loan Type', loan_type, 'write_off_amount')
+
+	# checking greater than 0 as there may be some minor precision error
+	if pending_amount < write_off_limit:
+		# update status as loan closure requested
+		frappe.db.set_value('Loan', loan, 'status', 'Loan Closure Requested')
+	else:
+		frappe.throw(_("Cannot close loan as there is an outstanding of {0}").format(pending_amount))
+
+@frappe.whitelist()
 def get_loan_application(loan_application):
 	loan = frappe.get_doc("Loan Application", loan_application)
 	if loan:
@@ -200,6 +222,7 @@
 	disbursement_entry.applicant = applicant
 	disbursement_entry.company = company
 	disbursement_entry.disbursement_date = nowdate()
+	disbursement_entry.posting_date = nowdate()
 
 	disbursement_entry.disbursed_amount = pending_amount
 	if as_dict:
@@ -223,6 +246,38 @@
 		return repayment_entry
 
 @frappe.whitelist()
+def make_loan_write_off(loan, company=None, posting_date=None, amount=0, as_dict=0):
+	if not company:
+		company = frappe.get_value('Loan', loan, 'company')
+
+	if not posting_date:
+		posting_date = getdate()
+
+	amounts = calculate_amounts(loan, posting_date)
+	pending_amount = amounts['pending_principal_amount']
+
+	if amount and (amount > pending_amount):
+		frappe.throw('Write Off amount cannot be greater than pending loan amount')
+
+	if not amount:
+		amount = pending_amount
+
+	# get default write off account from company master
+	write_off_account = frappe.get_value('Company', company, 'write_off_account')
+
+	write_off = frappe.new_doc('Loan Write Off')
+	write_off.loan = loan
+	write_off.posting_date = posting_date
+	write_off.write_off_account = write_off_account
+	write_off.write_off_amount = amount
+	write_off.save()
+
+	if as_dict:
+		return write_off.as_dict()
+	else:
+		return write_off
+
+@frappe.whitelist()
 def unpledge_security(loan=None, loan_security_pledge=None, as_dict=0, save=0, submit=0, approve=0):
 	# if loan is passed it will be considered as full unpledge
 	if loan:
diff --git a/erpnext/loan_management/doctype/loan/loan_dashboard.py b/erpnext/loan_management/doctype/loan/loan_dashboard.py
index 90d5ae2..7a8190f 100644
--- a/erpnext/loan_management/doctype/loan/loan_dashboard.py
+++ b/erpnext/loan_management/doctype/loan/loan_dashboard.py
@@ -13,7 +13,7 @@
 				'items': ['Loan Security Pledge', 'Loan Security Shortfall', 'Loan Disbursement']
 			},
 			{
-				'items': ['Loan Repayment', 'Loan Interest Accrual', 'Loan Security Unpledge']
+				'items': ['Loan Repayment', 'Loan Interest Accrual', 'Loan Write Off', 'Loan Security Unpledge']
 			}
 		]
 	}
\ No newline at end of file
diff --git a/erpnext/loan_management/doctype/loan/loan_list.js b/erpnext/loan_management/doctype/loan/loan_list.js
new file mode 100644
index 0000000..6591b72
--- /dev/null
+++ b/erpnext/loan_management/doctype/loan/loan_list.js
@@ -0,0 +1,16 @@
+// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
+// License: GNU General Public License v3. See license.txt
+
+frappe.listview_settings['Loan'] = {
+	get_indicator: function(doc) {
+		var status_color = {
+			"Draft": "red",
+			"Sanctioned": "blue",
+			"Disbursed": "orange",
+			"Partially Disbursed": "yellow",
+			"Loan Closure Requested": "green",
+			"Closed": "green"
+		};
+		return [__(doc.status), status_color[doc.status], "status,=,"+doc.status];
+	},
+};
diff --git a/erpnext/loan_management/doctype/loan/test_loan.py b/erpnext/loan_management/doctype/loan/test_loan.py
index 5a4a19a..10a7b11 100644
--- a/erpnext/loan_management/doctype/loan/test_loan.py
+++ b/erpnext/loan_management/doctype/loan/test_loan.py
@@ -14,7 +14,7 @@
 	process_loan_interest_accrual_for_term_loans)
 from erpnext.loan_management.doctype.loan_interest_accrual.loan_interest_accrual import days_in_year
 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 unpledge_security
+from erpnext.loan_management.doctype.loan.loan import unpledge_security, request_loan_closure, make_loan_write_off
 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
 from erpnext.loan_management.doctype.loan_disbursement.loan_disbursement import get_disbursal_amount
@@ -132,7 +132,7 @@
 		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 = create_demand_loan(self.applicant2, "Demand Loan", loan_application, posting_date='2019-10-01')
 		loan.submit()
 
 		self.assertEquals(loan.loan_amount, 1000000)
@@ -142,30 +142,30 @@
 
 		no_of_days = date_diff(last_date, first_date) + 1
 
-		accrued_interest_amount = (loan.loan_amount * loan.rate_of_interest * no_of_days) \
-			/ (days_in_year(get_datetime(first_date).year) * 100)
+		accrued_interest_amount = flt((loan.loan_amount * loan.rate_of_interest * no_of_days)
+			/ (days_in_year(get_datetime(first_date).year) * 100), 2)
 
 		make_loan_disbursement_entry(loan.name, loan.loan_amount, disbursement_date=first_date)
 
 		process_loan_interest_accrual_for_demand_loans(posting_date = last_date)
 
-		repayment_entry = create_repayment_entry(loan.name, self.applicant2, add_days(last_date, 10), "Regular Payment", 111118.68)
+		repayment_entry = create_repayment_entry(loan.name, self.applicant2, add_days(last_date, 10), 111119)
 		repayment_entry.save()
 		repayment_entry.submit()
 
-		penalty_amount = (accrued_interest_amount * 4 * 25) / (100 * days_in_year(get_datetime(first_date).year))
-		self.assertEquals(flt(repayment_entry.penalty_amount, 2), flt(penalty_amount, 2))
+		penalty_amount = (accrued_interest_amount * 5 * 25) / 100
+		self.assertEquals(flt(repayment_entry.penalty_amount,0), flt(penalty_amount, 0))
 
-		amounts = frappe.db.get_value('Loan Interest Accrual', {'loan': loan.name}, ['paid_interest_amount',
-			'paid_principal_amount'])
+		amounts = frappe.db.get_all('Loan Interest Accrual', {'loan': loan.name}, ['paid_interest_amount'])
 
 		loan.load_from_db()
 
-		self.assertEquals(amounts[0], repayment_entry.interest_payable)
-		self.assertEquals(flt(loan.total_principal_paid, 2), flt(repayment_entry.amount_paid -
-			 penalty_amount - amounts[0], 2))
+		total_interest_paid = amounts[0]['paid_interest_amount'] + amounts[1]['paid_interest_amount']
+		self.assertEquals(amounts[1]['paid_interest_amount'], repayment_entry.interest_payable)
+		self.assertEquals(flt(loan.total_principal_paid, 0), flt(repayment_entry.amount_paid -
+			 penalty_amount - total_interest_paid, 0))
 
-	def test_loan_closure_repayment(self):
+	def test_loan_closure(self):
 		pledge = [{
 			"loan_security": "Test Security 1",
 			"qty": 4000.00
@@ -174,7 +174,7 @@
 		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 = create_demand_loan(self.applicant2, "Demand Loan", loan_application, posting_date='2019-10-01')
 		loan.submit()
 
 		self.assertEquals(loan.loan_amount, 1000000)
@@ -184,10 +184,10 @@
 
 		no_of_days = date_diff(last_date, first_date) + 1
 
-		# Adding 6 since repayment is made 5 days late after due date
+		# Adding 5 since repayment is made 5 days late after due date
 		# and since payment type is loan closure so interest should be considered for those
-		# 6 days as well though in grace period
-		no_of_days += 6
+		# 5 days as well though in grace period
+		no_of_days += 5
 
 		accrued_interest_amount = (loan.loan_amount * loan.rate_of_interest * no_of_days) \
 			/ (days_in_year(get_datetime(first_date).year) * 100)
@@ -195,15 +195,17 @@
 		make_loan_disbursement_entry(loan.name, loan.loan_amount, disbursement_date=first_date)
 		process_loan_interest_accrual_for_demand_loans(posting_date = last_date)
 
-		repayment_entry = create_repayment_entry(loan.name, self.applicant2, add_days(last_date, 6),
-			"Loan Closure", flt(loan.loan_amount + accrued_interest_amount))
+		repayment_entry = create_repayment_entry(loan.name, self.applicant2, add_days(last_date, 5),
+			flt(loan.loan_amount + accrued_interest_amount))
+
 		repayment_entry.submit()
 
 		amount = frappe.db.get_value('Loan Interest Accrual', {'loan': loan.name}, ['sum(paid_interest_amount)'])
 
-		self.assertEquals(flt(amount, 2),flt(accrued_interest_amount, 2))
+		self.assertEquals(flt(amount, 0),flt(accrued_interest_amount, 0))
 		self.assertEquals(flt(repayment_entry.penalty_amount, 5), 0)
 
+		request_loan_closure(loan.name)
 		loan.load_from_db()
 		self.assertEquals(loan.status, "Loan Closure Requested")
 
@@ -230,8 +232,7 @@
 
 		process_loan_interest_accrual_for_term_loans(posting_date=nowdate())
 
-		repayment_entry = create_repayment_entry(loan.name, self.applicant2, add_days(nowdate(), 5),
-			"Regular Payment", 89768.75)
+		repayment_entry = create_repayment_entry(loan.name, self.applicant2, add_days(nowdate(), 5), 89768.75)
 
 		repayment_entry.submit()
 
@@ -281,7 +282,7 @@
 		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 = create_demand_loan(self.applicant2, "Demand Loan", loan_application, posting_date='2019-10-01')
 		loan.submit()
 
 		self.assertEquals(loan.loan_amount, 1000000)
@@ -291,7 +292,7 @@
 
 		no_of_days = date_diff(last_date, first_date) + 1
 
-		no_of_days += 6
+		no_of_days += 5
 
 		accrued_interest_amount = (loan.loan_amount * loan.rate_of_interest * no_of_days) \
 			/ (days_in_year(get_datetime(first_date).year) * 100)
@@ -299,10 +300,10 @@
 		make_loan_disbursement_entry(loan.name, loan.loan_amount, disbursement_date=first_date)
 		process_loan_interest_accrual_for_demand_loans(posting_date = last_date)
 
-		repayment_entry = create_repayment_entry(loan.name, self.applicant2, add_days(last_date, 6),
-			"Loan Closure", flt(loan.loan_amount + accrued_interest_amount))
+		repayment_entry = create_repayment_entry(loan.name, self.applicant2, add_days(last_date, 5), flt(loan.loan_amount + accrued_interest_amount))
 		repayment_entry.submit()
 
+		request_loan_closure(loan.name)
 		loan.load_from_db()
 		self.assertEquals(loan.status, "Loan Closure Requested")
 
@@ -317,9 +318,9 @@
 		self.assertEqual(loan.status, 'Closed')
 		self.assertEquals(sum(pledged_qty.values()), 0)
 
-		amounts = amounts = calculate_amounts(loan.name, add_days(last_date, 6), "Regular Repayment")
-		self.assertEqual(amounts['pending_principal_amount'], 0)
-		self.assertEqual(amounts['payable_principal_amount'], 0)
+		amounts = amounts = calculate_amounts(loan.name, add_days(last_date, 5))
+		self.assertTrue(amounts['pending_principal_amount'] < 0)
+		self.assertEquals(amounts['payable_principal_amount'], 0.0)
 		self.assertEqual(amounts['interest_amount'], 0)
 
 	def test_disbursal_check_with_shortfall(self):
@@ -381,7 +382,7 @@
 		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 = create_demand_loan(self.applicant2, "Demand Loan", loan_application, posting_date='2019-10-01')
 		loan.submit()
 
 		self.assertEquals(loan.loan_amount, 1000000)
@@ -391,7 +392,7 @@
 
 		no_of_days = date_diff(last_date, first_date) + 1
 
-		no_of_days += 6
+		no_of_days += 5
 
 		accrued_interest_amount = (loan.loan_amount * loan.rate_of_interest * no_of_days) \
 			/ (days_in_year(get_datetime(first_date).year) * 100)
@@ -399,20 +400,192 @@
 		make_loan_disbursement_entry(loan.name, loan.loan_amount, disbursement_date=first_date)
 		process_loan_interest_accrual_for_demand_loans(posting_date = last_date)
 
-		amounts = calculate_amounts(loan.name, add_days(last_date, 6), "Regular Repayment")
+		amounts = calculate_amounts(loan.name, add_days(last_date, 5))
 
-		repayment_entry = create_repayment_entry(loan.name, self.applicant2, add_days(last_date, 6),
-			"Loan Closure", flt(loan.loan_amount + accrued_interest_amount))
+		repayment_entry = create_repayment_entry(loan.name, self.applicant2, add_days(last_date, 5), flt(loan.loan_amount + accrued_interest_amount))
 		repayment_entry.submit()
 
 		amounts = frappe.db.get_value('Loan Interest Accrual', {'loan': loan.name}, ['paid_interest_amount',
 			'paid_principal_amount'])
 
+		request_loan_closure(loan.name)
 		loan.load_from_db()
 		self.assertEquals(loan.status, "Loan Closure Requested")
 
-		amounts = calculate_amounts(loan.name, add_days(last_date, 6), "Regular Repayment")
-		self.assertEquals(amounts['pending_principal_amount'], 0.0)
+		amounts = calculate_amounts(loan.name, add_days(last_date, 5))
+		self.assertTrue(amounts['pending_principal_amount'] < 0.0)
+
+	def test_partial_unaccrued_interest_payment(self):
+		pledge = [{
+			"loan_security": "Test Security 1",
+			"qty": 4000.00
+		}]
+
+		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='2019-10-01')
+		loan.submit()
+
+		self.assertEquals(loan.loan_amount, 1000000)
+
+		first_date = '2019-10-01'
+		last_date = '2019-10-30'
+
+		no_of_days = date_diff(last_date, first_date) + 1
+
+		no_of_days += 5.5
+
+		# get partial unaccrued interest amount
+		paid_amount = (loan.loan_amount * loan.rate_of_interest * no_of_days) \
+			/ (days_in_year(get_datetime(first_date).year) * 100)
+
+		make_loan_disbursement_entry(loan.name, loan.loan_amount, disbursement_date=first_date)
+		process_loan_interest_accrual_for_demand_loans(posting_date = last_date)
+
+		amounts = calculate_amounts(loan.name, add_days(last_date, 5))
+
+		repayment_entry = create_repayment_entry(loan.name, self.applicant2, add_days(last_date, 5),
+			paid_amount)
+
+		repayment_entry.submit()
+		repayment_entry.load_from_db()
+
+		partial_accrued_interest_amount = (loan.loan_amount * loan.rate_of_interest * 5) \
+			/ (days_in_year(get_datetime(first_date).year) * 100)
+
+		interest_amount = flt(amounts['interest_amount'] + partial_accrued_interest_amount, 2)
+		self.assertEqual(flt(repayment_entry.total_interest_paid, 0), flt(interest_amount, 0))
+
+	def test_penalty(self):
+		pledge = [{
+			"loan_security": "Test Security 1",
+			"qty": 4000.00
+		}]
+
+		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='2019-10-01')
+		loan.submit()
+
+		self.assertEquals(loan.loan_amount, 1000000)
+
+		first_date = '2019-10-01'
+		last_date = '2019-10-30'
+
+		make_loan_disbursement_entry(loan.name, loan.loan_amount, disbursement_date=first_date)
+		process_loan_interest_accrual_for_demand_loans(posting_date = last_date)
+
+		amounts = calculate_amounts(loan.name, add_days(last_date, 1))
+		paid_amount = amounts['interest_amount']/2
+
+		repayment_entry = create_repayment_entry(loan.name, self.applicant2, add_days(last_date, 5),
+			paid_amount)
+
+		repayment_entry.submit()
+
+		# 30 days - grace period
+		penalty_days = 30 - 4
+		penalty_applicable_amount = flt(amounts['interest_amount']/2, 2)
+		penalty_amount = flt((((penalty_applicable_amount * 25) / 100) * penalty_days), 2)
+		process = process_loan_interest_accrual_for_demand_loans(posting_date = '2019-11-30')
+
+		calculated_penalty_amount = frappe.db.get_value('Loan Interest Accrual',
+			{'process_loan_interest_accrual': process, 'loan': loan.name}, 'penalty_amount')
+
+		self.assertEquals(calculated_penalty_amount, penalty_amount)
+
+	def test_loan_write_off_limit(self):
+		pledge = [{
+			"loan_security": "Test Security 1",
+			"qty": 4000.00
+		}]
+
+		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='2019-10-01')
+		loan.submit()
+
+		self.assertEquals(loan.loan_amount, 1000000)
+
+		first_date = '2019-10-01'
+		last_date = '2019-10-30'
+
+		no_of_days = date_diff(last_date, first_date) + 1
+		no_of_days += 5
+
+		accrued_interest_amount = (loan.loan_amount * loan.rate_of_interest * no_of_days) \
+			/ (days_in_year(get_datetime(first_date).year) * 100)
+
+		make_loan_disbursement_entry(loan.name, loan.loan_amount, disbursement_date=first_date)
+		process_loan_interest_accrual_for_demand_loans(posting_date = last_date)
+
+		# repay 50 less so that it can be automatically written off
+		repayment_entry = create_repayment_entry(loan.name, self.applicant2, add_days(last_date, 5),
+			flt(loan.loan_amount + accrued_interest_amount - 50))
+
+		repayment_entry.submit()
+
+		amount = frappe.db.get_value('Loan Interest Accrual', {'loan': loan.name}, ['sum(paid_interest_amount)'])
+
+		self.assertEquals(flt(amount, 0),flt(accrued_interest_amount, 0))
+		self.assertEquals(flt(repayment_entry.penalty_amount, 5), 0)
+
+		amounts = calculate_amounts(loan.name, add_days(last_date, 5))
+		self.assertEquals(flt(amounts['pending_principal_amount'], 0), 50)
+
+		request_loan_closure(loan.name)
+		loan.load_from_db()
+		self.assertEquals(loan.status, "Loan Closure Requested")
+
+	def test_loan_amount_write_off(self):
+		pledge = [{
+			"loan_security": "Test Security 1",
+			"qty": 4000.00
+		}]
+
+		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='2019-10-01')
+		loan.submit()
+
+		self.assertEquals(loan.loan_amount, 1000000)
+
+		first_date = '2019-10-01'
+		last_date = '2019-10-30'
+
+		no_of_days = date_diff(last_date, first_date) + 1
+		no_of_days += 5
+
+		accrued_interest_amount = (loan.loan_amount * loan.rate_of_interest * no_of_days) \
+			/ (days_in_year(get_datetime(first_date).year) * 100)
+
+		make_loan_disbursement_entry(loan.name, loan.loan_amount, disbursement_date=first_date)
+		process_loan_interest_accrual_for_demand_loans(posting_date = last_date)
+
+		# repay 100 less so that it can be automatically written off
+		repayment_entry = create_repayment_entry(loan.name, self.applicant2, add_days(last_date, 5),
+			flt(loan.loan_amount + accrued_interest_amount - 100))
+
+		repayment_entry.submit()
+
+		amount = frappe.db.get_value('Loan Interest Accrual', {'loan': loan.name}, ['sum(paid_interest_amount)'])
+
+		self.assertEquals(flt(amount, 0),flt(accrued_interest_amount, 0))
+		self.assertEquals(flt(repayment_entry.penalty_amount, 5), 0)
+
+		amounts = calculate_amounts(loan.name, add_days(last_date, 5))
+		self.assertEquals(flt(amounts['pending_principal_amount'], 0), 100)
+
+		we = make_loan_write_off(loan.name, amount=amounts['pending_principal_amount'])
+		we.submit()
+
+		amounts = calculate_amounts(loan.name, add_days(last_date, 5))
+		self.assertEquals(flt(amounts['pending_principal_amount'], 0), 0)
+
 
 def create_loan_accounts():
 	if not frappe.db.exists("Account", "Loans and Advances (Assets) - _TC"):
@@ -496,7 +669,8 @@
 			"interest_income_account": interest_income_account,
 			"penalty_income_account": penalty_income_account,
 			"repayment_method": repayment_method,
-			"repayment_periods": repayment_periods
+			"repayment_periods": repayment_periods,
+			"write_off_amount": 100
 		}).insert()
 
 		loan_type.submit()
@@ -532,7 +706,7 @@
 			"haircut": 50.00,
 		}).insert(ignore_permissions=True)
 
-def create_loan_security_pledge(applicant, pledges, loan_application):
+def create_loan_security_pledge(applicant, pledges, loan_application=None, loan=None):
 
 	lsp = frappe.new_doc("Loan Security Pledge")
 	lsp.applicant_type = 'Customer'
@@ -540,11 +714,13 @@
 	lsp.company = "_Test Company"
 	lsp.loan_application = loan_application
 
+	if loan:
+		lsp.loan = loan
+
 	for pledge in pledges:
 		lsp.append('securities', {
 			"loan_security": pledge['loan_security'],
-			"qty": pledge['qty'],
-			"haircut": pledge['haircut']
+			"qty": pledge['qty']
 		})
 
 	lsp.save()
@@ -582,12 +758,11 @@
 			"valid_upto": to_date
 		}).insert(ignore_permissions=True)
 
-def create_repayment_entry(loan, applicant, posting_date, payment_type, paid_amount):
+def create_repayment_entry(loan, applicant, posting_date, paid_amount):
 
 	lr = frappe.get_doc({
 		"doctype": "Loan Repayment",
 		"against_loan": loan,
-		"payment_type": payment_type,
 		"company": "_Test Company",
 		"posting_date": posting_date or nowdate(),
 		"applicant": applicant,
diff --git a/erpnext/loan_management/doctype/loan_application/loan_application.py b/erpnext/loan_management/doctype/loan_application/loan_application.py
index bac6e63..e59db4c 100644
--- a/erpnext/loan_management/doctype/loan_application/loan_application.py
+++ b/erpnext/loan_management/doctype/loan_application/loan_application.py
@@ -127,6 +127,7 @@
 		target_doc.loan_account = account_details.loan_account
 		target_doc.interest_income_account = account_details.interest_income_account
 		target_doc.penalty_income_account = account_details.penalty_income_account
+		target_doc.loan_application = source_name
 
 
 	doclist = get_mapped_doc("Loan Application", source_name, {
diff --git a/erpnext/loan_management/doctype/loan_disbursement/loan_disbursement.json b/erpnext/loan_management/doctype/loan_disbursement/loan_disbursement.json
index c437a98..cd5df4d 100644
--- a/erpnext/loan_management/doctype/loan_disbursement/loan_disbursement.json
+++ b/erpnext/loan_management/doctype/loan_disbursement/loan_disbursement.json
@@ -26,19 +26,24 @@
   {
    "fieldname": "against_loan",
    "fieldtype": "Link",
+   "in_list_view": 1,
    "label": "Against Loan ",
-   "options": "Loan"
+   "options": "Loan",
+   "reqd": 1
   },
   {
    "fieldname": "disbursement_date",
    "fieldtype": "Date",
-   "label": "Disbursement Date"
+   "label": "Disbursement Date",
+   "reqd": 1
   },
   {
    "fieldname": "disbursed_amount",
    "fieldtype": "Currency",
    "label": "Disbursed Amount",
-   "options": "Company:company:default_currency"
+   "non_negative": 1,
+   "options": "Company:company:default_currency",
+   "reqd": 1
   },
   {
    "fieldname": "amended_from",
@@ -53,17 +58,21 @@
    "fetch_from": "against_loan.company",
    "fieldname": "company",
    "fieldtype": "Link",
+   "in_list_view": 1,
    "label": "Company",
    "options": "Company",
-   "read_only": 1
+   "read_only": 1,
+   "reqd": 1
   },
   {
    "fetch_from": "against_loan.applicant",
    "fieldname": "applicant",
    "fieldtype": "Dynamic Link",
+   "in_list_view": 1,
    "label": "Applicant",
    "options": "applicant_type",
-   "read_only": 1
+   "read_only": 1,
+   "reqd": 1
   },
   {
    "collapsible": 1,
@@ -102,9 +111,11 @@
    "fetch_from": "against_loan.applicant_type",
    "fieldname": "applicant_type",
    "fieldtype": "Select",
+   "in_list_view": 1,
    "label": "Applicant Type",
    "options": "Employee\nMember\nCustomer",
-   "read_only": 1
+   "read_only": 1,
+   "reqd": 1
   },
   {
    "fieldname": "bank_account",
@@ -117,9 +128,10 @@
    "fieldtype": "Column Break"
   }
  ],
+ "index_web_pages_for_search": 1,
  "is_submittable": 1,
  "links": [],
- "modified": "2020-04-29 05:20:41.629911",
+ "modified": "2020-11-06 10:04:30.882322",
  "modified_by": "Administrator",
  "module": "Loan Management",
  "name": "Loan Disbursement",
diff --git a/erpnext/loan_management/doctype/loan_disbursement/loan_disbursement.py b/erpnext/loan_management/doctype/loan_disbursement/loan_disbursement.py
index 260fada..f341e81 100644
--- a/erpnext/loan_management/doctype/loan_disbursement/loan_disbursement.py
+++ b/erpnext/loan_management/doctype/loan_disbursement/loan_disbursement.py
@@ -17,6 +17,7 @@
 
 	def validate(self):
 		self.set_missing_values()
+		self.validate_disbursal_amount()
 
 	def on_submit(self):
 		self.set_status_and_amounts()
@@ -40,57 +41,21 @@
 		if not self.bank_account and self.applicant_type == "Customer":
 			self.bank_account = frappe.db.get_value("Customer", self.applicant, "default_bank_account")
 
-	def set_status_and_amounts(self, cancel=0):
+	def validate_disbursal_amount(self):
+		possible_disbursal_amount = get_disbursal_amount(self.against_loan)
 
+		if self.disbursed_amount > possible_disbursal_amount:
+			frappe.throw(_("Disbursed Amount cannot be greater than {0}").format(possible_disbursal_amount))
+
+	def set_status_and_amounts(self, cancel=0):
 		loan_details = frappe.get_all("Loan",
 			fields = ["loan_amount", "disbursed_amount", "total_payment", "total_principal_paid", "total_interest_payable",
 				"status", "is_term_loan", "is_secured_loan"], filters= { "name": self.against_loan })[0]
 
 		if cancel:
-			disbursed_amount = loan_details.disbursed_amount - self.disbursed_amount
-			total_payment = loan_details.total_payment
-
-			if loan_details.disbursed_amount > loan_details.loan_amount:
-				topup_amount = loan_details.disbursed_amount - loan_details.loan_amount
-				if topup_amount > self.disbursed_amount:
-					topup_amount = self.disbursed_amount
-
-				total_payment = total_payment - topup_amount
-
-			if disbursed_amount == 0:
-				status = "Sanctioned"
-			elif disbursed_amount >= loan_details.loan_amount:
-				status = "Disbursed"
-			else:
-				status = "Partially Disbursed"
+			disbursed_amount, status, total_payment = self.get_values_on_cancel(loan_details)
 		else:
-			disbursed_amount = self.disbursed_amount + loan_details.disbursed_amount
-			total_payment = loan_details.total_payment
-
-			possible_disbursal_amount = get_disbursal_amount(self.against_loan)
-
-			if self.disbursed_amount > possible_disbursal_amount:
-				frappe.throw(_("Disbursed Amount cannot be greater than {0}").format(possible_disbursal_amount))
-
-			if loan_details.status == "Disbursed" and not loan_details.is_term_loan:
-				process_loan_interest_accrual_for_demand_loans(posting_date=add_days(self.disbursement_date, -1),
-					loan=self.against_loan)
-
-			if disbursed_amount > loan_details.loan_amount:
-				topup_amount = disbursed_amount - loan_details.loan_amount
-
-				if topup_amount < 0:
-					topup_amount = 0
-
-				if topup_amount > self.disbursed_amount:
-					topup_amount = self.disbursed_amount
-
-				total_payment = total_payment + topup_amount
-
-			if flt(disbursed_amount) >= loan_details.loan_amount:
-				status = "Disbursed"
-			else:
-				status = "Partially Disbursed"
+			disbursed_amount, status, total_payment = self.get_values_on_submit(loan_details)
 
 		frappe.db.set_value("Loan", self.against_loan, {
 			"disbursement_date": self.disbursement_date,
@@ -99,6 +64,53 @@
 			"total_payment": total_payment
 		})
 
+	def get_values_on_cancel(self, loan_details):
+		disbursed_amount = loan_details.disbursed_amount - self.disbursed_amount
+		total_payment = loan_details.total_payment
+
+		if loan_details.disbursed_amount > loan_details.loan_amount:
+			topup_amount = loan_details.disbursed_amount - loan_details.loan_amount
+			if topup_amount > self.disbursed_amount:
+				topup_amount = self.disbursed_amount
+
+			total_payment = total_payment - topup_amount
+
+		if disbursed_amount == 0:
+			status = "Sanctioned"
+
+		elif disbursed_amount >= loan_details.loan_amount:
+			status = "Disbursed"
+		else:
+			status = "Partially Disbursed"
+
+		return disbursed_amount, status, total_payment
+
+	def get_values_on_submit(self, loan_details):
+		disbursed_amount = self.disbursed_amount + loan_details.disbursed_amount
+		total_payment = loan_details.total_payment
+
+		if loan_details.status in ("Disbursed", "Partially Disbursed") and not loan_details.is_term_loan:
+			process_loan_interest_accrual_for_demand_loans(posting_date=add_days(self.disbursement_date, -1),
+				loan=self.against_loan, accrual_type="Disbursement")
+
+		if disbursed_amount > loan_details.loan_amount:
+			topup_amount = disbursed_amount - loan_details.loan_amount
+
+			if topup_amount < 0:
+				topup_amount = 0
+
+			if topup_amount > self.disbursed_amount:
+				topup_amount = self.disbursed_amount
+
+			total_payment = total_payment + topup_amount
+
+		if flt(disbursed_amount) >= loan_details.loan_amount:
+			status = "Disbursed"
+		else:
+			status = "Partially Disbursed"
+
+		return disbursed_amount, status, total_payment
+
 	def make_gl_entries(self, cancel=0, adv_adj=0):
 		gle_map = []
 		loan_details = frappe.get_doc("Loan", self.against_loan)
@@ -111,7 +123,7 @@
 				"debit_in_account_currency": self.disbursed_amount,
 				"against_voucher_type": "Loan",
 				"against_voucher": self.against_loan,
-				"remarks": "Against Loan:" + self.against_loan,
+				"remarks": _("Disbursement against loan:") + self.against_loan,
 				"cost_center": self.cost_center,
 				"party_type": self.applicant_type,
 				"party": self.applicant,
@@ -127,10 +139,8 @@
 				"credit_in_account_currency": self.disbursed_amount,
 				"against_voucher_type": "Loan",
 				"against_voucher": self.against_loan,
-				"remarks": "Against Loan:" + self.against_loan,
+				"remarks": _("Disbursement against loan:") + self.against_loan,
 				"cost_center": self.cost_center,
-				"party_type": self.applicant_type,
-				"party": self.applicant,
 				"posting_date": self.disbursement_date
 			})
 		)
@@ -155,15 +165,16 @@
 	pledged_securities = get_pledged_security_qty(loan)
 
 	for security, qty in pledged_securities.items():
-		security_value += (loan_security_price_map.get(security) * qty * hair_cut_map.get(security))/100
+		after_haircut_percentage = 100 - hair_cut_map.get(security)
+		security_value += (loan_security_price_map.get(security) * qty * after_haircut_percentage)/100
 
 	return security_value
 
 @frappe.whitelist()
-def get_disbursal_amount(loan):
-	loan_details = frappe.get_all("Loan", fields = ["loan_amount", "disbursed_amount", "total_payment",
-		"total_principal_paid", "total_interest_payable", "status", "is_term_loan", "is_secured_loan"],
-		filters= { "name": loan })[0]
+def get_disbursal_amount(loan, on_current_security_price=0):
+	loan_details = frappe.get_value("Loan", loan, ["loan_amount", "disbursed_amount", "total_payment",
+		"total_principal_paid", "total_interest_payable", "status", "is_term_loan", "is_secured_loan",
+		"maximum_loan_amount"], as_dict=1)
 
 	if loan_details.is_secured_loan and frappe.get_all('Loan Security Shortfall', filters={'loan': loan,
 		'status': 'Pending'}):
@@ -173,17 +184,24 @@
 		pending_principal_amount = flt(loan_details.total_payment) - flt(loan_details.total_interest_payable) \
 			- flt(loan_details.total_principal_paid)
 	else:
-		pending_principal_amount = flt(loan_details.disbursed_amount)
+		pending_principal_amount = flt(loan_details.disbursed_amount) - flt(loan_details.total_interest_payable) \
+			- flt(loan_details.total_principal_paid)
 
 	security_value = 0.0
-	if loan_details.is_secured_loan:
+	if loan_details.is_secured_loan and on_current_security_price:
 		security_value = get_total_pledged_security_value(loan)
 
+	if loan_details.is_secured_loan and not on_current_security_price:
+		security_value = flt(loan_details.maximum_loan_amount)
+
 	if not security_value and not loan_details.is_secured_loan:
 		security_value = flt(loan_details.loan_amount)
 
 	disbursal_amount = flt(security_value) - flt(pending_principal_amount)
 
+	if loan_details.is_term_loan and (disbursal_amount + loan_details.loan_amount) > loan_details.loan_amount:
+		disbursal_amount = loan_details.loan_amount - loan_details.disbursed_amount
+
 	return disbursal_amount
 
 
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 2cb2637..a875387 100644
--- a/erpnext/loan_management/doctype/loan_disbursement/test_loan_disbursement.py
+++ b/erpnext/loan_management/doctype/loan_disbursement/test_loan_disbursement.py
@@ -8,9 +8,10 @@
 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.loan_management.doctype.loan_interest_accrual.loan_interest_accrual import days_in_year, get_per_day_interest
 from erpnext.selling.doctype.customer.test_customer import get_customer_dict
 from erpnext.loan_management.doctype.loan_application.loan_application import create_pledge
+from erpnext.loan_management.doctype.loan_repayment.loan_repayment import calculate_amounts
 
 class TestLoanDisbursement(unittest.TestCase):
 
@@ -60,8 +61,7 @@
 		self.assertRaises(frappe.ValidationError, make_loan_disbursement_entry, loan.name,
 			500000, first_date)
 
-		repayment_entry = create_repayment_entry(loan.name, self.applicant, add_days(get_last_day(nowdate()), 5),
-			"Regular Payment", 611095.89)
+		repayment_entry = create_repayment_entry(loan.name, self.applicant, add_days(get_last_day(nowdate()), 5), 611095.89)
 
 		repayment_entry.submit()
 		loan.reload()
@@ -69,3 +69,50 @@
 		# After repayment loan disbursement entry should go through
 		make_loan_disbursement_entry(loan.name, 500000, disbursement_date=add_days(last_date, 16))
 
+		# check for disbursement accrual
+		loan_interest_accrual = frappe.db.get_value('Loan Interest Accrual', {'loan': loan.name,
+			'accrual_type': 'Disbursement'})
+
+		self.assertTrue(loan_interest_accrual)
+
+	def test_loan_topup_with_additional_pledge(self):
+		pledge = [{
+			"loan_security": "Test Security 1",
+			"qty": 4000.00
+		}]
+
+		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_application, posting_date='2019-10-01')
+		loan.submit()
+
+		self.assertEquals(loan.loan_amount, 1000000)
+
+		first_date = '2019-10-01'
+		last_date = '2019-10-30'
+
+		# Disbursed 10,00,000 amount
+		make_loan_disbursement_entry(loan.name, loan.loan_amount, disbursement_date=first_date)
+		process_loan_interest_accrual_for_demand_loans(posting_date = last_date)
+		amounts = calculate_amounts(loan.name, add_days(last_date, 1))
+
+		previous_interest = amounts['interest_amount']
+
+		pledge1 = [{
+			"loan_security": "Test Security 1",
+			"qty": 2000.00
+		}]
+
+		create_loan_security_pledge(self.applicant, pledge1, loan=loan.name)
+
+		# Topup 500000
+		make_loan_disbursement_entry(loan.name, 500000, disbursement_date=add_days(last_date, 1))
+		process_loan_interest_accrual_for_demand_loans(posting_date = add_days(last_date, 15))
+		amounts = calculate_amounts(loan.name, add_days(last_date, 15))
+
+		per_day_interest = get_per_day_interest(1500000, 13.5, '2019-10-30')
+		interest = per_day_interest * 15
+
+		self.assertEquals(amounts['pending_principal_amount'], 1500000)
+		self.assertEquals(amounts['interest_amount'], flt(interest + previous_interest, 2))
diff --git a/erpnext/loan_management/doctype/loan_interest_accrual/loan_interest_accrual.json b/erpnext/loan_management/doctype/loan_interest_accrual/loan_interest_accrual.json
index 5fc3e8f..f157f0d 100644
--- a/erpnext/loan_management/doctype/loan_interest_accrual/loan_interest_accrual.json
+++ b/erpnext/loan_management/doctype/loan_interest_accrual/loan_interest_accrual.json
@@ -14,6 +14,7 @@
   "column_break_4",
   "company",
   "posting_date",
+  "accrual_type",
   "is_term_loan",
   "section_break_7",
   "pending_principal_amount",
@@ -22,9 +23,11 @@
   "column_break_14",
   "interest_amount",
   "paid_interest_amount",
+  "penalty_amount",
   "section_break_15",
   "process_loan_interest_accrual",
   "repayment_schedule_name",
+  "last_accrual_date",
   "amended_from"
  ],
  "fields": [
@@ -139,6 +142,7 @@
    "read_only": 1
   },
   {
+   "depends_on": "eval:doc.is_term_loan",
    "fieldname": "paid_principal_amount",
    "fieldtype": "Currency",
    "label": "Paid Principal Amount",
@@ -149,12 +153,32 @@
    "fieldtype": "Currency",
    "label": "Paid Interest Amount",
    "options": "Company:company:default_currency"
+  },
+  {
+   "fieldname": "accrual_type",
+   "fieldtype": "Select",
+   "label": "Accrual Type",
+   "options": "Regular\nRepayment\nDisbursement"
+  },
+  {
+   "fieldname": "penalty_amount",
+   "fieldtype": "Currency",
+   "label": "Penalty Amount",
+   "options": "Company:company:default_currency"
+  },
+  {
+   "fieldname": "last_accrual_date",
+   "fieldtype": "Date",
+   "hidden": 1,
+   "label": "Last Accrual Date",
+   "read_only": 1
   }
  ],
  "in_create": 1,
+ "index_web_pages_for_search": 1,
  "is_submittable": 1,
  "links": [],
- "modified": "2020-04-16 11:24:23.258404",
+ "modified": "2020-11-07 05:49:25.448875",
  "modified_by": "Administrator",
  "module": "Loan Management",
  "name": "Loan Interest Accrual",
diff --git a/erpnext/loan_management/doctype/loan_interest_accrual/loan_interest_accrual.py b/erpnext/loan_management/doctype/loan_interest_accrual/loan_interest_accrual.py
index 2d959bf..d17f5af 100644
--- a/erpnext/loan_management/doctype/loan_interest_accrual/loan_interest_accrual.py
+++ b/erpnext/loan_management/doctype/loan_interest_accrual/loan_interest_accrual.py
@@ -22,6 +22,8 @@
 		if not self.interest_amount and not self.payable_principal_amount:
 			frappe.throw(_("Interest Amount or Principal Amount is mandatory"))
 
+		if not self.last_accrual_date:
+			self.last_accrual_date = get_last_accrual_date(self.loan)
 
 	def on_submit(self):
 		self.make_gl_entries()
@@ -50,7 +52,8 @@
 					"debit_in_account_currency": self.interest_amount,
 					"against_voucher_type": "Loan",
 					"against_voucher": self.loan,
-					"remarks": _("Against Loan:") + self.loan,
+					"remarks": _("Interest accrued from {0} to {1} against loan: {2}").format(
+						self.last_accrual_date, self.posting_date, self.loan),
 					"cost_center": erpnext.get_default_cost_center(self.company),
 					"posting_date": self.posting_date
 				})
@@ -59,14 +62,13 @@
 			gle_map.append(
 				self.get_gl_dict({
 					"account": self.interest_income_account,
-					"party_type": self.applicant_type,
-					"party": self.applicant,
 					"against": self.loan_account,
 					"credit": self.interest_amount,
 					"credit_in_account_currency":  self.interest_amount,
 					"against_voucher_type": "Loan",
 					"against_voucher": self.loan,
-					"remarks": _("Against Loan:") + self.loan,
+					"remarks": ("Interest accrued from {0} to {1} against loan: {2}").format(
+						self.last_accrual_date, self.posting_date, self.loan),
 					"cost_center": erpnext.get_default_cost_center(self.company),
 					"posting_date": self.posting_date
 				})
@@ -79,19 +81,23 @@
 # For Eg: If Loan disbursement date is '01-09-2019' and disbursed amount is 1000000 and
 # rate of interest is 13.5 then first loan interest accural will be on '01-10-2019'
 # which means interest will be accrued for 30 days which should be equal to 11095.89
-def calculate_accrual_amount_for_demand_loans(loan, posting_date, process_loan_interest):
+def calculate_accrual_amount_for_demand_loans(loan, posting_date, process_loan_interest, accrual_type):
+	from erpnext.loan_management.doctype.loan_repayment.loan_repayment import calculate_amounts
+
 	no_of_days = get_no_of_days_for_interest_accural(loan, posting_date)
+	precision = cint(frappe.db.get_default("currency_precision")) or 2
 
 	if no_of_days <= 0:
 		return
 
 	if loan.status == 'Disbursed':
 		pending_principal_amount = flt(loan.total_payment) - flt(loan.total_interest_payable) \
-			- flt(loan.total_principal_paid)
+			- flt(loan.total_principal_paid) - flt(loan.written_off_amount)
 	else:
-		pending_principal_amount = loan.disbursed_amount
+		pending_principal_amount = flt(loan.disbursed_amount) - flt(loan.total_interest_payable) \
+			- flt(loan.total_principal_paid) - flt(loan.written_off_amount)
 
-	interest_per_day = (pending_principal_amount * loan.rate_of_interest) / (days_in_year(get_datetime(posting_date).year) * 100)
+	interest_per_day = get_per_day_interest(pending_principal_amount, loan.rate_of_interest, posting_date)
 	payable_interest = interest_per_day * no_of_days
 
 	args = frappe._dict({
@@ -102,13 +108,16 @@
 		'loan_account': loan.loan_account,
 		'pending_principal_amount': pending_principal_amount,
 		'interest_amount': payable_interest,
+		'penalty_amount': calculate_amounts(loan.name, posting_date)['penalty_amount'],
 		'process_loan_interest': process_loan_interest,
-		'posting_date': posting_date
+		'posting_date': posting_date,
+		'accrual_type': accrual_type
 	})
 
-	make_loan_interest_accrual_entry(args)
+	if flt(payable_interest, precision) > 0.0:
+		make_loan_interest_accrual_entry(args)
 
-def make_accrual_interest_entry_for_demand_loans(posting_date, process_loan_interest, open_loans=None, loan_type=None):
+def make_accrual_interest_entry_for_demand_loans(posting_date, process_loan_interest, open_loans=None, loan_type=None, accrual_type="Regular"):
 	query_filters = {
 		"status": ('in', ['Disbursed', 'Partially Disbursed']),
 		"docstatus": 1
@@ -123,13 +132,13 @@
 		open_loans = frappe.get_all("Loan",
 			fields=["name", "total_payment", "total_amount_paid", "loan_account", "interest_income_account",
 				"is_term_loan", "status", "disbursement_date", "disbursed_amount", "applicant_type", "applicant",
-				"rate_of_interest", "total_interest_payable", "total_principal_paid", "repayment_start_date"],
+				"rate_of_interest", "total_interest_payable", "written_off_amount", "total_principal_paid", "repayment_start_date"],
 			filters=query_filters)
 
 	for loan in open_loans:
-		calculate_accrual_amount_for_demand_loans(loan, posting_date, process_loan_interest)
+		calculate_accrual_amount_for_demand_loans(loan, posting_date, process_loan_interest, accrual_type)
 
-def make_accrual_interest_entry_for_term_loans(posting_date, process_loan_interest, term_loan=None, loan_type=None):
+def make_accrual_interest_entry_for_term_loans(posting_date, process_loan_interest, term_loan=None, loan_type=None, accrual_type="Regular"):
 	curr_date = posting_date or add_days(nowdate(), 1)
 
 	term_loans = get_term_loans(curr_date, term_loan, loan_type)
@@ -148,7 +157,8 @@
 			'payable_principal': loan.principal_amount,
 			'process_loan_interest': process_loan_interest,
 			'repayment_schedule_name': loan.payment_entry,
-			'posting_date': posting_date
+			'posting_date': posting_date,
+			'accrual_type': accrual_type
 		})
 
 		make_loan_interest_accrual_entry(args)
@@ -192,31 +202,33 @@
 	loan_interest_accrual.loan_account = args.loan_account
 	loan_interest_accrual.pending_principal_amount = flt(args.pending_principal_amount, precision)
 	loan_interest_accrual.interest_amount = flt(args.interest_amount, precision)
+	loan_interest_accrual.penalty_amount = flt(args.penalty_amount, precision)
 	loan_interest_accrual.posting_date = args.posting_date or nowdate()
 	loan_interest_accrual.process_loan_interest_accrual = args.process_loan_interest
 	loan_interest_accrual.repayment_schedule_name = args.repayment_schedule_name
 	loan_interest_accrual.payable_principal_amount = args.payable_principal
+	loan_interest_accrual.accrual_type = args.accrual_type
 
 	loan_interest_accrual.save()
 	loan_interest_accrual.submit()
 
 
 def get_no_of_days_for_interest_accural(loan, posting_date):
-	last_interest_accrual_date = get_last_accural_date_in_current_month(loan)
+	last_interest_accrual_date = get_last_accrual_date(loan.name)
 
 	no_of_days = date_diff(posting_date or nowdate(), last_interest_accrual_date) + 1
 
 	return no_of_days
 
-def get_last_accural_date_in_current_month(loan):
+def get_last_accrual_date(loan):
 	last_posting_date = frappe.db.sql(""" SELECT MAX(posting_date) from `tabLoan Interest Accrual`
-		WHERE loan = %s""", (loan.name))
+		WHERE loan = %s and docstatus = 1""", (loan))
 
 	if last_posting_date[0][0]:
 		# interest for last interest accrual date is already booked, so add 1 day
 		return add_days(last_posting_date[0][0], 1)
 	else:
-		return loan.disbursement_date
+		return frappe.db.get_value('Loan', loan, 'disbursement_date')
 
 def days_in_year(year):
 	days = 365
@@ -226,3 +238,11 @@
 
 	return days
 
+def get_per_day_interest(principal_amount, rate_of_interest, posting_date=None):
+	if not posting_date:
+		posting_date = getdate()
+
+	precision = cint(frappe.db.get_default("currency_precision")) or 2
+
+	return flt((principal_amount * rate_of_interest) / (days_in_year(get_datetime(posting_date).year) * 100), precision)
+
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 4b85b21..46a6440 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
@@ -5,7 +5,7 @@
 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_loan_security_price,
+from erpnext.loan_management.doctype.loan.test_loan import (create_loan_type, create_loan_security_price,
 	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
@@ -57,4 +57,4 @@
 
 		loan_interest_accural = frappe.get_doc("Loan Interest Accrual", {'loan': loan.name})
 
-		self.assertEquals(flt(loan_interest_accural.interest_amount, 2), flt(accrued_interest_amount, 2))
+		self.assertEquals(flt(loan_interest_accural.interest_amount, 0), flt(accrued_interest_amount, 0))
diff --git a/erpnext/loan_management/doctype/loan_repayment/loan_repayment.json b/erpnext/loan_management/doctype/loan_repayment/loan_repayment.json
index 5942455..2b5df4b 100644
--- a/erpnext/loan_management/doctype/loan_repayment/loan_repayment.json
+++ b/erpnext/loan_management/doctype/loan_repayment/loan_repayment.json
@@ -10,11 +10,11 @@
   "applicant_type",
   "applicant",
   "loan_type",
-  "payment_type",
   "column_break_3",
   "company",
   "posting_date",
   "is_term_loan",
+  "rate_of_interest",
   "payment_details_section",
   "due_date",
   "pending_principal_amount",
@@ -31,6 +31,7 @@
   "column_break_21",
   "reference_date",
   "principal_amount_paid",
+  "total_interest_paid",
   "repayment_details",
   "amended_from"
  ],
@@ -96,15 +97,6 @@
    "fieldtype": "Column Break"
   },
   {
-   "default": "Regular Payment",
-   "fieldname": "payment_type",
-   "fieldtype": "Select",
-   "in_list_view": 1,
-   "label": "Payment Type",
-   "options": "\nRegular Payment\nLoan Closure",
-   "reqd": 1
-  },
-  {
    "fieldname": "payable_amount",
    "fieldtype": "Currency",
    "label": "Payable Amount",
@@ -116,6 +108,7 @@
    "fieldname": "amount_paid",
    "fieldtype": "Currency",
    "label": "Amount Paid",
+   "non_negative": 1,
    "options": "Company:company:default_currency",
    "reqd": 1
   },
@@ -195,6 +188,7 @@
    "fieldtype": "Currency",
    "hidden": 1,
    "label": "Principal Amount Paid",
+   "options": "Company:company:default_currency",
    "read_only": 1
   },
   {
@@ -217,11 +211,27 @@
    "hidden": 1,
    "label": "Repayment Details",
    "options": "Loan Repayment Detail"
+  },
+  {
+   "fieldname": "total_interest_paid",
+   "fieldtype": "Currency",
+   "hidden": 1,
+   "label": "Total Interest Paid",
+   "options": "Company:company:default_currency",
+   "read_only": 1
+  },
+  {
+   "fetch_from": "loan_type.rate_of_interest",
+   "fieldname": "rate_of_interest",
+   "fieldtype": "Percent",
+   "label": "Rate Of Interest",
+   "read_only": 1
   }
  ],
+ "index_web_pages_for_search": 1,
  "is_submittable": 1,
  "links": [],
- "modified": "2020-05-16 09:40:15.581165",
+ "modified": "2020-11-05 10:06:58.792841",
  "modified_by": "Administrator",
  "module": "Loan Management",
  "name": "Loan Repayment",
diff --git a/erpnext/loan_management/doctype/loan_repayment/loan_repayment.py b/erpnext/loan_management/doctype/loan_repayment/loan_repayment.py
index 97dbc44..415ba99 100644
--- a/erpnext/loan_management/doctype/loan_repayment/loan_repayment.py
+++ b/erpnext/loan_management/doctype/loan_repayment/loan_repayment.py
@@ -14,14 +14,15 @@
 from erpnext.accounts.general_ledger import make_gl_entries
 from erpnext.loan_management.doctype.loan_security_shortfall.loan_security_shortfall import update_shortfall_status
 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 get_per_day_interest, get_last_accrual_date
 
 class LoanRepayment(AccountsController):
 
 	def validate(self):
-		amounts = calculate_amounts(self.against_loan, self.posting_date, self.payment_type)
+		amounts = calculate_amounts(self.against_loan, self.posting_date)
 		self.set_missing_values(amounts)
 		self.validate_amount()
-		self.allocate_amounts(amounts['pending_accrual_entries'])
+		self.allocate_amounts(amounts)
 
 	def before_submit(self):
 		self.book_unaccrued_interest()
@@ -32,8 +33,8 @@
 
 	def on_cancel(self):
 		self.mark_as_unpaid()
-		self.make_gl_entries(cancel=1)
 		self.ignore_linked_doctypes = ['GL Entry']
+		self.make_gl_entries(cancel=1)
 
 	def set_missing_values(self, amounts):
 		precision = cint(frappe.db.get_default("currency_precision")) or 2
@@ -72,29 +73,36 @@
 			msg = _("Paid amount cannot be less than {0}").format(self.penalty_amount)
 			frappe.throw(msg)
 
-		if self.payment_type == "Loan Closure" and flt(self.amount_paid, precision) < flt(self.payable_amount, precision):
-			msg = _("Amount of {0} is required for Loan closure").format(self.payable_amount)
-			frappe.throw(msg)
-
 	def book_unaccrued_interest(self):
-		if self.payment_type == 'Loan Closure':
-			total_interest_paid = 0
-			for payment in self.repayment_details:
-				total_interest_paid += payment.paid_interest_amount
+		precision = cint(frappe.db.get_default("currency_precision")) or 2
+		if self.total_interest_paid > self.interest_payable:
+			if not self.is_term_loan:
+				# get last loan interest accrual date
+				last_accrual_date = get_last_accrual_date(self.against_loan)
 
-			if total_interest_paid < self.interest_payable:
-				if not self.is_term_loan:
-					process = process_loan_interest_accrual_for_demand_loans(posting_date=self.posting_date,
-						loan=self.against_loan)
+				# get posting date upto which interest has to be accrued
+				per_day_interest = flt(get_per_day_interest(self.pending_principal_amount,
+					self.rate_of_interest, self.posting_date), 2)
 
-					lia = frappe.db.get_value('Loan Interest Accrual', {'process_loan_interest_accrual':
-						process}, ['name', 'interest_amount', 'payable_principal_amount'], as_dict=1)
+				no_of_days = flt(flt(self.total_interest_paid - self.interest_payable,
+					precision)/per_day_interest, 0) - 1
 
-					self.append('repayment_details', {
-						'loan_interest_accrual': lia.name,
-						'paid_interest_amount': lia.interest_amount,
-						'paid_principal_amount': lia.payable_principal_amount
-					})
+				posting_date = add_days(last_accrual_date, no_of_days)
+
+				# book excess interest paid
+				process = process_loan_interest_accrual_for_demand_loans(posting_date=posting_date,
+					loan=self.against_loan, accrual_type="Repayment")
+
+				# get loan interest accrual to update paid amount
+				lia = frappe.db.get_value('Loan Interest Accrual', {'process_loan_interest_accrual':
+					process}, ['name', 'interest_amount', 'payable_principal_amount'], as_dict=1)
+
+				self.append('repayment_details', {
+					'loan_interest_accrual': lia.name,
+					'paid_interest_amount': flt(self.total_interest_paid - self.interest_payable, precision),
+					'paid_principal_amount': 0.0,
+					'accrual_type': 'Repayment'
+				})
 
 	def update_paid_amount(self):
 		precision = cint(frappe.db.get_default("currency_precision")) or 2
@@ -108,12 +116,6 @@
 				WHERE name = %s""",
 				(flt(payment.paid_principal_amount, precision), flt(payment.paid_interest_amount, precision), payment.loan_interest_accrual))
 
-		if flt(loan.total_principal_paid + self.principal_amount_paid, precision) >= flt(loan.total_payment, precision):
-			if loan.is_secured_loan:
-				frappe.db.set_value("Loan", self.against_loan, "status", "Loan Closure Requested")
-			else:
-				frappe.db.set_value("Loan", self.against_loan, "status", "Closed")
-
 		frappe.db.sql(""" UPDATE `tabLoan` SET total_amount_paid = %s, total_principal_paid = %s
 			WHERE name = %s """, (loan.total_amount_paid + self.amount_paid,
 			loan.total_principal_paid + self.principal_amount_paid, self.against_loan))
@@ -123,6 +125,8 @@
 	def mark_as_unpaid(self):
 		loan = frappe.get_doc("Loan", self.against_loan)
 
+		no_of_repayments = len(self.repayment_details)
+
 		for payment in self.repayment_details:
 			frappe.db.sql(""" UPDATE `tabLoan Interest Accrual`
 				SET paid_principal_amount = `paid_principal_amount` - %s,
@@ -130,6 +134,12 @@
 				WHERE name = %s""",
 				(payment.paid_principal_amount, payment.paid_interest_amount, payment.loan_interest_accrual))
 
+			# Cancel repayment interest accrual
+			# checking idx as a preventive measure, repayment accrual will always be the last entry
+			if payment.accrual_type == 'Repayment' and payment.idx == no_of_repayments:
+				lia_doc = frappe.get_doc('Loan Interest Accrual', payment.loan_interest_accrual)
+				lia_doc.cancel()
+
 		frappe.db.sql(""" UPDATE `tabLoan` SET total_amount_paid = %s, total_principal_paid = %s
 			WHERE name = %s """, (loan.total_amount_paid - self.amount_paid,
 			loan.total_principal_paid - self.principal_amount_paid, self.against_loan))
@@ -137,15 +147,17 @@
 		if loan.status == "Loan Closure Requested":
 			frappe.db.set_value("Loan", self.against_loan, "status", "Disbursed")
 
-	def allocate_amounts(self, paid_entries):
+	def allocate_amounts(self, repayment_details):
+		precision = cint(frappe.db.get_default("currency_precision")) or 2
+
 		self.set('repayment_details', [])
 		self.principal_amount_paid = 0
 		total_interest_paid = 0
 		interest_paid = self.amount_paid - self.penalty_amount
 
-		if self.amount_paid - self.penalty_amount > 0 and paid_entries:
+		if self.amount_paid - self.penalty_amount > 0:
 			interest_paid = self.amount_paid - self.penalty_amount
-			for lia, amounts in iteritems(paid_entries):
+			for lia, amounts in iteritems(repayment_details.get('pending_accrual_entries', [])):
 				if amounts['interest_amount'] + amounts['payable_principal_amount'] <= interest_paid:
 					interest_amount = amounts['interest_amount']
 					paid_principal = amounts['payable_principal_amount']
@@ -169,9 +181,24 @@
 					'paid_principal_amount': paid_principal
 				})
 
-		if self.payment_type == 'Loan Closure' and total_interest_paid < self.interest_payable:
-			unaccrued_interest = self.interest_payable - total_interest_paid
-			interest_paid -= unaccrued_interest
+		if repayment_details['unaccrued_interest'] and interest_paid:
+			# no of days for which to accrue interest
+			# Interest can only be accrued for an entire day and not partial
+			if interest_paid > repayment_details['unaccrued_interest']:
+				per_day_interest = flt(get_per_day_interest(self.pending_principal_amount,
+					self.rate_of_interest, self.posting_date), precision)
+				interest_paid -= repayment_details['unaccrued_interest']
+				total_interest_paid += repayment_details['unaccrued_interest']
+			else:
+				# get no of days for which interest can be paid
+				per_day_interest = flt(get_per_day_interest(self.pending_principal_amount,
+					self.rate_of_interest, self.posting_date), precision)
+
+				no_of_days = cint(interest_paid/per_day_interest)
+				total_interest_paid += no_of_days * per_day_interest
+				interest_paid -= no_of_days * per_day_interest
+
+		self.total_interest_paid = total_interest_paid
 
 		if interest_paid:
 			self.principal_amount_paid += interest_paid
@@ -189,7 +216,7 @@
 					"debit_in_account_currency": self.penalty_amount,
 					"against_voucher_type": "Loan",
 					"against_voucher": self.against_loan,
-					"remarks": _("Against Loan:") + self.against_loan,
+					"remarks": _("Penalty against loan:") + self.against_loan,
 					"cost_center": self.cost_center,
 					"party_type": self.applicant_type,
 					"party": self.applicant,
@@ -205,10 +232,8 @@
 					"credit_in_account_currency": self.penalty_amount,
 					"against_voucher_type": "Loan",
 					"against_voucher": self.against_loan,
-					"remarks": _("Against Loan:") + self.against_loan,
+					"remarks": _("Penalty against loan:") + self.against_loan,
 					"cost_center": self.cost_center,
-					"party_type": self.applicant_type,
-					"party": self.applicant,
 					"posting_date": getdate(self.posting_date)
 				})
 			)
@@ -219,13 +244,11 @@
 				"against": loan_details.loan_account + ", " + loan_details.interest_income_account
 						+ ", " + loan_details.penalty_income_account,
 				"debit": self.amount_paid,
-				"debit_in_account_currency": self.amount_paid ,
+				"debit_in_account_currency": self.amount_paid,
 				"against_voucher_type": "Loan",
 				"against_voucher": self.against_loan,
-				"remarks": _("Against Loan:") + self.against_loan,
+				"remarks": _("Repayment against Loan: ") + self.against_loan,
 				"cost_center": self.cost_center,
-				"party_type": self.applicant_type,
-				"party": self.applicant,
 				"posting_date": getdate(self.posting_date)
 			})
 		)
@@ -240,7 +263,7 @@
 				"credit_in_account_currency": self.amount_paid,
 				"against_voucher_type": "Loan",
 				"against_voucher": self.against_loan,
-				"remarks": _("Against Loan:") + self.against_loan,
+				"remarks": _("Repayment against Loan: ") + self.against_loan,
 				"cost_center": self.cost_center,
 				"posting_date": getdate(self.posting_date)
 			})
@@ -273,7 +296,8 @@
 	unpaid_accrued_entries = frappe.db.sql(
 		"""
 			SELECT name, posting_date, interest_amount - paid_interest_amount as interest_amount,
-				payable_principal_amount - paid_principal_amount as payable_principal_amount
+				payable_principal_amount - paid_principal_amount as payable_principal_amount,
+				accrual_type
 			FROM
 				`tabLoan Interest Accrual`
 			WHERE
@@ -282,6 +306,7 @@
 				payable_principal_amount - paid_principal_amount > 0)
 			AND
 				docstatus = 1
+			ORDER BY posting_date
 		""", (against_loan), as_dict=1)
 
 	return unpaid_accrued_entries
@@ -289,7 +314,7 @@
 # This function returns the amounts that are payable at the time of loan repayment based on posting date
 # So it pulls all the unpaid Loan Interest Accrual Entries and calculates the penalty if applicable
 
-def get_amounts(amounts, against_loan, posting_date, payment_type):
+def get_amounts(amounts, against_loan, posting_date):
 	precision = cint(frappe.db.get_default("currency_precision")) or 2
 
 	against_loan_doc = frappe.get_doc("Loan", against_loan)
@@ -311,10 +336,10 @@
 
 		due_date = add_days(entry.posting_date, 1)
 		no_of_late_days = date_diff(posting_date,
-			add_days(due_date, loan_type_details.grace_period_in_days))
+			add_days(due_date, loan_type_details.grace_period_in_days)) + 1
 
-		if no_of_late_days > 0 and (not against_loan_doc.repay_from_salary):
-			penalty_amount += (entry.interest_amount * (loan_type_details.penalty_interest_rate / 100) * no_of_late_days)/365
+		if no_of_late_days > 0 and (not against_loan_doc.repay_from_salary) and entry.accrual_type == 'Regular':
+			penalty_amount += (entry.interest_amount * (loan_type_details.penalty_interest_rate / 100) * no_of_late_days)
 
 		total_pending_interest += entry.interest_amount
 		payable_principal_amount += entry.payable_principal_amount
@@ -324,23 +349,27 @@
 			'payable_principal_amount': flt(entry.payable_principal_amount, precision)
 		})
 
-		if not final_due_date:
+		if due_date and not final_due_date:
 			final_due_date = add_days(due_date, loan_type_details.grace_period_in_days)
 
 	if against_loan_doc.status in ('Disbursed', 'Loan Closure Requested', 'Closed'):
-		pending_principal_amount = against_loan_doc.total_payment - against_loan_doc.total_principal_paid - against_loan_doc.total_interest_payable
+		pending_principal_amount = against_loan_doc.total_payment - against_loan_doc.total_principal_paid \
+			- against_loan_doc.total_interest_payable - against_loan_doc.written_off_amount
 	else:
-		pending_principal_amount = against_loan_doc.disbursed_amount
+		pending_principal_amount = against_loan_doc.disbursed_amount - against_loan_doc.total_principal_paid \
+			- against_loan_doc.total_interest_payable - against_loan_doc.written_off_amount
 
-	if payment_type == "Loan Closure":
-		if due_date:
-			pending_days = date_diff(posting_date, due_date) + 1
-		else:
-			pending_days = date_diff(posting_date, against_loan_doc.disbursement_date) + 1
+	unaccrued_interest = 0
+	if due_date:
+		pending_days = date_diff(posting_date, due_date) + 1
+	else:
+		last_accrual_date = get_last_accrual_date(against_loan_doc.name)
+		pending_days = date_diff(posting_date, last_accrual_date) + 1
 
-		payable_principal_amount = pending_principal_amount
-		per_day_interest = (payable_principal_amount * (loan_type_details.rate_of_interest / 100))/365
-		total_pending_interest += (pending_days * per_day_interest)
+	if pending_days > 0:
+		principal_amount = flt(pending_principal_amount, precision)
+		per_day_interest = get_per_day_interest(principal_amount, loan_type_details.rate_of_interest, posting_date)
+		unaccrued_interest += (pending_days * flt(per_day_interest, precision))
 
 	amounts["pending_principal_amount"] = flt(pending_principal_amount, precision)
 	amounts["payable_principal_amount"] = flt(payable_principal_amount, precision)
@@ -348,6 +377,7 @@
 	amounts["penalty_amount"] = flt(penalty_amount, precision)
 	amounts["payable_amount"] = flt(payable_principal_amount + total_pending_interest + penalty_amount, precision)
 	amounts["pending_accrual_entries"] = pending_accrual_entries
+	amounts["unaccrued_interest"] = unaccrued_interest
 
 	if final_due_date:
 		amounts["due_date"] = final_due_date
@@ -355,7 +385,7 @@
 	return amounts
 
 @frappe.whitelist()
-def calculate_amounts(against_loan, posting_date, payment_type):
+def calculate_amounts(against_loan, posting_date, payment_type=''):
 
 	amounts = {
 		'penalty_amount': 0.0,
@@ -363,10 +393,17 @@
 		'pending_principal_amount': 0.0,
 		'payable_principal_amount': 0.0,
 		'payable_amount': 0.0,
+		'unaccrued_interest': 0.0,
 		'due_date': ''
 	}
 
-	amounts = get_amounts(amounts, against_loan, posting_date, payment_type)
+	amounts = get_amounts(amounts, against_loan, posting_date)
+
+	# update values for closure
+	if payment_type == 'Loan Closure':
+		amounts['payable_principal_amount'] = amounts['pending_principal_amount']
+		amounts['interest_amount'] += amounts['unaccrued_interest']
+		amounts['payable_amount'] = amounts['payable_principal_amount'] + amounts['interest_amount']
 
 	return amounts
 
diff --git a/erpnext/loan_management/doctype/loan_repayment_detail/loan_repayment_detail.json b/erpnext/loan_management/doctype/loan_repayment_detail/loan_repayment_detail.json
index cff1dbb..4b9b191 100644
--- a/erpnext/loan_management/doctype/loan_repayment_detail/loan_repayment_detail.json
+++ b/erpnext/loan_management/doctype/loan_repayment_detail/loan_repayment_detail.json
@@ -7,7 +7,8 @@
  "field_order": [
   "loan_interest_accrual",
   "paid_principal_amount",
-  "paid_interest_amount"
+  "paid_interest_amount",
+  "accrual_type"
  ],
  "fields": [
   {
@@ -27,11 +28,20 @@
    "fieldtype": "Currency",
    "label": "Paid Interest Amount",
    "options": "Company:company:default_currency"
+  },
+  {
+   "fetch_from": "loan_interest_accrual.accrual_type",
+   "fetch_if_empty": 1,
+   "fieldname": "accrual_type",
+   "fieldtype": "Select",
+   "label": "Accrual Type",
+   "options": "Regular\nRepayment\nDisbursement"
   }
  ],
+ "index_web_pages_for_search": 1,
  "istable": 1,
  "links": [],
- "modified": "2020-04-15 21:50:03.837019",
+ "modified": "2020-10-23 08:09:18.267030",
  "modified_by": "Administrator",
  "module": "Loan Management",
  "name": "Loan Repayment Detail",
diff --git a/erpnext/loan_management/doctype/loan_security/loan_security.json b/erpnext/loan_management/doctype/loan_security/loan_security.json
index 1d0bb30..c698601 100644
--- a/erpnext/loan_management/doctype/loan_security/loan_security.json
+++ b/erpnext/loan_management/doctype/loan_security/loan_security.json
@@ -25,6 +25,7 @@
   },
   {
    "fetch_from": "loan_security_type.haircut",
+   "fetch_if_empty": 1,
    "fieldname": "haircut",
    "fieldtype": "Percent",
    "label": "Haircut %"
@@ -64,8 +65,9 @@
    "reqd": 1
   }
  ],
+ "index_web_pages_for_search": 1,
  "links": [],
- "modified": "2020-04-29 13:21:26.043492",
+ "modified": "2020-10-26 07:34:48.601766",
  "modified_by": "Administrator",
  "module": "Loan Management",
  "name": "Loan Security",
diff --git a/erpnext/loan_management/doctype/loan_security_pledge/loan_security_pledge.py b/erpnext/loan_management/doctype/loan_security_pledge/loan_security_pledge.py
index 2bb6fd8..cbc8376 100644
--- a/erpnext/loan_management/doctype/loan_security_pledge/loan_security_pledge.py
+++ b/erpnext/loan_management/doctype/loan_security_pledge/loan_security_pledge.py
@@ -78,7 +78,7 @@
 		self.maximum_loan_value = maximum_loan_value
 
 def update_loan(loan, maximum_value_against_pledge):
-	maximum_loan_value = frappe.db.get_value('Loan', {'name': loan}, ['maximum_loan_value'])
+	maximum_loan_value = frappe.db.get_value('Loan', {'name': loan}, ['maximum_loan_amount'])
 
-	frappe.db.sql(""" UPDATE `tabLoan` SET maximum_loan_value=%s, is_secured_loan=1
+	frappe.db.sql(""" UPDATE `tabLoan` SET maximum_loan_amount=%s, is_secured_loan=1
 		WHERE name=%s""", (maximum_loan_value + maximum_value_against_pledge, loan))
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 0f42bde..8ec0bfb 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
@@ -22,7 +22,7 @@
 	if security_value >= loan_security_shortfall.shortfall_amount:
 		frappe.db.set_value("Loan Security Shortfall", loan_security_shortfall.name, {
 			"status": "Completed",
-			"shortfall_value": loan_security_shortfall.shortfall_amount})
+			"shortfall_amount": 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/doctype/loan_security_unpledge/loan_security_unpledge.py b/erpnext/loan_management/doctype/loan_security_unpledge/loan_security_unpledge.py
index b3eb600..c29f325 100644
--- a/erpnext/loan_management/doctype/loan_security_unpledge/loan_security_unpledge.py
+++ b/erpnext/loan_management/doctype/loan_security_unpledge/loan_security_unpledge.py
@@ -42,18 +42,20 @@
 				"valid_upto": (">=", get_datetime())
 			}, as_list=1))
 
-		total_payment, principal_paid, interest_payable = frappe.get_value("Loan", self.loan, ['total_payment', 'total_principal_paid',
-			'total_interest_payable'])
+		total_payment, principal_paid, interest_payable, written_off_amount = frappe.get_value("Loan", self.loan, ['total_payment', 'total_principal_paid',
+			'total_interest_payable', 'written_off_amount'])
 
-		pending_principal_amount = flt(total_payment) - flt(interest_payable) - flt(principal_paid)
+		pending_principal_amount = flt(total_payment) - flt(interest_payable) - flt(principal_paid) - flt(written_off_amount)
 		security_value = 0
 
 		for security in self.securities:
 			pledged_qty = pledge_qty_map.get(security.loan_security, 0)
 			if security.qty > pledged_qty:
-				frappe.throw(_("""Row {0}: {1} {2} of {3} is pledged against Loan {4}.
-					You are trying to unpledge more""").format(security.idx, pledged_qty, security.uom,
-					frappe.bold(security.loan_security), frappe.bold(self.loan)))
+				msg = _("Row {0}: {1} {2} of {3} is pledged against Loan {4}.").format(security.idx, pledged_qty, security.uom,
+					frappe.bold(security.loan_security), frappe.bold(self.loan))
+				msg += "<br>"
+				msg += _("You are trying to unpledge more.")
+				frappe.throw(msg, title=_("Loan Security Unpledge Error"))
 
 			qty_after_unpledge = pledged_qty - security.qty
 			ltv_ratio = ltv_ratio_map.get(security.loan_security_type)
@@ -65,10 +67,18 @@
 			security_value += qty_after_unpledge * current_price
 
 		if not security_value and flt(pending_principal_amount, 2) > 0:
-			frappe.throw("Cannot Unpledge, loan to value ratio is breaching")
+			self._throw(security_value, pending_principal_amount, ltv_ratio)
 
 		if security_value and flt(pending_principal_amount/security_value) * 100 > ltv_ratio:
-			frappe.throw("Cannot Unpledge, loan to value ratio is breaching")
+			self._throw(security_value, pending_principal_amount, ltv_ratio)
+
+	def _throw(self, security_value, pending_principal_amount, ltv_ratio):
+		msg = _("Loan Security Value after unpledge is {0}").format(frappe.bold(security_value))
+		msg += '<br>'
+		msg += _("Pending principal amount is {0}").format(frappe.bold(flt(pending_principal_amount, 2)))
+		msg += '<br>'
+		msg += _("Loan To Security Value ratio must always be {0}").format(frappe.bold(ltv_ratio))
+		frappe.throw(msg, title=_("Loan To Value ratio breach"))
 
 	def on_update_after_submit(self):
 		self.approve()
diff --git a/erpnext/loan_management/doctype/loan_type/loan_type.json b/erpnext/loan_management/doctype/loan_type/loan_type.json
index 669490a..18a9731 100644
--- a/erpnext/loan_management/doctype/loan_type/loan_type.json
+++ b/erpnext/loan_management/doctype/loan_type/loan_type.json
@@ -11,6 +11,7 @@
   "rate_of_interest",
   "penalty_interest_rate",
   "grace_period_in_days",
+  "write_off_amount",
   "column_break_2",
   "company",
   "is_term_loan",
@@ -76,7 +77,6 @@
    "reqd": 1
   },
   {
-   "description": "This account is used for booking loan repayments from the borrower and also disbursing loans to the borrower",
    "fieldname": "payment_account",
    "fieldtype": "Link",
    "label": "Payment Account",
@@ -84,7 +84,6 @@
    "reqd": 1
   },
   {
-   "description": "This account is capital account which is used to allocate capital for loan disbursal account ",
    "fieldname": "loan_account",
    "fieldtype": "Link",
    "label": "Loan Account",
@@ -96,7 +95,6 @@
    "fieldtype": "Column Break"
   },
   {
-   "description": "This account will be used for booking loan interest accruals",
    "fieldname": "interest_income_account",
    "fieldtype": "Link",
    "label": "Interest Income Account",
@@ -104,7 +102,6 @@
    "reqd": 1
   },
   {
-   "description": "This account will be used for booking penalties levied due to delayed repayments",
    "fieldname": "penalty_income_account",
    "fieldtype": "Link",
    "label": "Penalty Income Account",
@@ -113,7 +110,6 @@
   },
   {
    "default": "0",
-   "description": "If this is not checked the loan by default will be considered as a Demand Loan",
    "fieldname": "is_term_loan",
    "fieldtype": "Check",
    "label": "Is Term Loan"
@@ -145,17 +141,27 @@
    "label": "Company",
    "options": "Company",
    "reqd": 1
+  },
+  {
+   "allow_on_submit": 1,
+   "description": "Pending amount that will be automatically ignored on loan closure request ",
+   "fieldname": "write_off_amount",
+   "fieldtype": "Currency",
+   "label": "Write Off Amount ",
+   "options": "Company:company:default_currency"
   }
  ],
+ "index_web_pages_for_search": 1,
  "is_submittable": 1,
  "links": [],
- "modified": "2020-06-07 18:55:59.346292",
+ "modified": "2020-10-26 07:13:55.029811",
  "modified_by": "Administrator",
  "module": "Loan Management",
  "name": "Loan Type",
  "owner": "Administrator",
  "permissions": [
   {
+   "cancel": 1,
    "create": 1,
    "delete": 1,
    "email": 1,
@@ -165,6 +171,7 @@
    "report": 1,
    "role": "Loan Manager",
    "share": 1,
+   "submit": 1,
    "write": 1
   },
   {
diff --git a/erpnext/loan_management/doctype/loan_write_off/__init__.py b/erpnext/loan_management/doctype/loan_write_off/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/loan_management/doctype/loan_write_off/__init__.py
diff --git a/erpnext/loan_management/doctype/loan_write_off/loan_write_off.js b/erpnext/loan_management/doctype/loan_write_off/loan_write_off.js
new file mode 100644
index 0000000..4e3319c
--- /dev/null
+++ b/erpnext/loan_management/doctype/loan_write_off/loan_write_off.js
@@ -0,0 +1,36 @@
+// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+{% include 'erpnext/loan_management/loan_common.js' %};
+
+frappe.ui.form.on('Loan Write Off', {
+	loan: function(frm) {
+		frm.trigger('show_pending_principal_amount');
+	},
+	onload: function(frm) {
+		frm.trigger('show_pending_principal_amount');
+	},
+	refresh: function(frm) {
+		frm.set_query('write_off_account', function(){
+			return {
+				filters: {
+					'company': frm.doc.company,
+					'root_type': 'Expense',
+					'is_group': 0
+				}
+			}
+		});
+	},
+	show_pending_principal_amount: function(frm) {
+		if (frm.doc.loan && frm.doc.docstatus === 0) {
+			frappe.db.get_value('Loan', frm.doc.loan, ['total_payment', 'total_interest_payable',
+				'total_principal_paid', 'written_off_amount'], function(values) {
+				frm.set_df_property('write_off_amount', 'description',
+					"Pending principal amount is " + cstr(flt(values.total_payment - values.total_interest_payable
+						- values.total_principal_paid - values.written_off_amount, 2)));
+				frm.refresh_field('write_off_amount');
+			});
+
+		}
+	}
+});
diff --git a/erpnext/loan_management/doctype/loan_write_off/loan_write_off.json b/erpnext/loan_management/doctype/loan_write_off/loan_write_off.json
new file mode 100644
index 0000000..4617a62
--- /dev/null
+++ b/erpnext/loan_management/doctype/loan_write_off/loan_write_off.json
@@ -0,0 +1,157 @@
+{
+ "actions": [],
+ "autoname": "LM-WO-.#####",
+ "creation": "2020-10-16 11:09:14.495066",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "loan",
+  "applicant_type",
+  "applicant",
+  "column_break_3",
+  "company",
+  "posting_date",
+  "accounting_dimensions_section",
+  "cost_center",
+  "section_break_9",
+  "write_off_account",
+  "column_break_11",
+  "write_off_amount",
+  "amended_from"
+ ],
+ "fields": [
+  {
+   "fieldname": "loan",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "label": "Loan",
+   "options": "Loan",
+   "reqd": 1
+  },
+  {
+   "default": "Today",
+   "fieldname": "posting_date",
+   "fieldtype": "Date",
+   "in_list_view": 1,
+   "label": "Posting Date",
+   "reqd": 1
+  },
+  {
+   "fieldname": "column_break_3",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fetch_from": "loan.company",
+   "fieldname": "company",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "label": "Company",
+   "options": "Company",
+   "read_only": 1,
+   "reqd": 1
+  },
+  {
+   "fetch_from": "loan.applicant_type",
+   "fieldname": "applicant_type",
+   "fieldtype": "Select",
+   "label": "Applicant Type",
+   "options": "Employee\nMember\nCustomer",
+   "read_only": 1
+  },
+  {
+   "fetch_from": "loan.applicant",
+   "fieldname": "applicant",
+   "fieldtype": "Dynamic Link",
+   "label": "Applicant ",
+   "options": "applicant_type",
+   "read_only": 1
+  },
+  {
+   "collapsible": 1,
+   "fieldname": "accounting_dimensions_section",
+   "fieldtype": "Section Break",
+   "label": "Accounting Dimensions"
+  },
+  {
+   "fieldname": "cost_center",
+   "fieldtype": "Link",
+   "label": "Cost Center",
+   "options": "Cost Center"
+  },
+  {
+   "fieldname": "section_break_9",
+   "fieldtype": "Section Break",
+   "label": "Write Off Details"
+  },
+  {
+   "fieldname": "write_off_account",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "label": "Write Off Account",
+   "options": "Account",
+   "reqd": 1
+  },
+  {
+   "fieldname": "write_off_amount",
+   "fieldtype": "Currency",
+   "label": "Write Off Amount",
+   "options": "Company:company:default_currency",
+   "reqd": 1
+  },
+  {
+   "fieldname": "column_break_11",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "amended_from",
+   "fieldtype": "Link",
+   "label": "Amended From",
+   "no_copy": 1,
+   "options": "Loan Write Off",
+   "print_hide": 1,
+   "read_only": 1
+  }
+ ],
+ "index_web_pages_for_search": 1,
+ "is_submittable": 1,
+ "links": [],
+ "modified": "2020-10-26 07:13:43.663924",
+ "modified_by": "Administrator",
+ "module": "Loan Management",
+ "name": "Loan Write Off",
+ "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": "Loan Manager",
+   "share": 1,
+   "submit": 1,
+   "write": 1
+  }
+ ],
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/loan_management/doctype/loan_write_off/loan_write_off.py b/erpnext/loan_management/doctype/loan_write_off/loan_write_off.py
new file mode 100644
index 0000000..54a3f2c
--- /dev/null
+++ b/erpnext/loan_management/doctype/loan_write_off/loan_write_off.py
@@ -0,0 +1,88 @@
+# -*- 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, erpnext
+from frappe import _
+from frappe.utils import getdate, flt, cint
+from erpnext.controllers.accounts_controller import AccountsController
+from erpnext.accounts.general_ledger import make_gl_entries
+
+class LoanWriteOff(AccountsController):
+	def validate(self):
+		self.set_missing_values()
+		self.validate_write_off_amount()
+
+	def set_missing_values(self):
+		if not self.cost_center:
+			self.cost_center = erpnext.get_default_cost_center(self.company)
+
+	def validate_write_off_amount(self):
+		precision = cint(frappe.db.get_default("currency_precision")) or 2
+		total_payment, principal_paid, interest_payable, written_off_amount = frappe.get_value("Loan", self.loan,
+			['total_payment', 'total_principal_paid','total_interest_payable', 'written_off_amount'])
+
+		pending_principal_amount = flt(flt(total_payment) - flt(interest_payable) - flt(principal_paid) - flt(written_off_amount),
+			precision)
+
+		if self.write_off_amount > pending_principal_amount:
+			frappe.throw(_("Write off amount cannot be greater than pending principal amount"))
+
+	def on_submit(self):
+		self.update_outstanding_amount()
+		self.make_gl_entries()
+
+	def on_cancel(self):
+		self.update_outstanding_amount(cancel=1)
+		self.ignore_linked_doctypes = ['GL Entry']
+		self.make_gl_entries(cancel=1)
+
+	def update_outstanding_amount(self, cancel=0):
+		written_off_amount = frappe.db.get_value('Loan', self.loan, 'written_off_amount')
+
+		if cancel:
+			written_off_amount -= self.write_off_amount
+		else:
+			written_off_amount += self.write_off_amount
+
+		frappe.db.set_value('Loan', self.loan, 'written_off_amount', written_off_amount)
+
+
+	def make_gl_entries(self, cancel=0):
+		gl_entries = []
+		loan_details = frappe.get_doc("Loan", self.loan)
+
+		gl_entries.append(
+			self.get_gl_dict({
+				"account": self.write_off_account,
+				"against": loan_details.loan_account,
+				"debit": self.write_off_amount,
+				"debit_in_account_currency": self.write_off_amount,
+				"against_voucher_type": "Loan",
+				"against_voucher": self.loan,
+				"remarks": _("Against Loan:") + self.loan,
+				"cost_center": self.cost_center,
+				"posting_date": getdate(self.posting_date)
+			})
+		)
+
+		gl_entries.append(
+			self.get_gl_dict({
+				"account": loan_details.loan_account,
+				"party_type": loan_details.applicant_type,
+				"party": loan_details.applicant,
+				"against": self.write_off_account,
+				"credit": self.write_off_amount,
+				"credit_in_account_currency": self.write_off_amount,
+				"against_voucher_type": "Loan",
+				"against_voucher": self.loan,
+				"remarks": _("Against Loan:") + self.loan,
+				"cost_center": self.cost_center,
+				"posting_date": getdate(self.posting_date)
+			})
+		)
+
+		make_gl_entries(gl_entries, cancel=cancel, merge_entries=False)
+
+
diff --git a/erpnext/loan_management/doctype/loan_write_off/test_loan_write_off.py b/erpnext/loan_management/doctype/loan_write_off/test_loan_write_off.py
new file mode 100644
index 0000000..9f6700e
--- /dev/null
+++ b/erpnext/loan_management/doctype/loan_write_off/test_loan_write_off.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 TestLoanWriteOff(unittest.TestCase):
+	pass
diff --git a/erpnext/loan_management/doctype/pledge/pledge.json b/erpnext/loan_management/doctype/pledge/pledge.json
index f22a21e..801e3a3 100644
--- a/erpnext/loan_management/doctype/pledge/pledge.json
+++ b/erpnext/loan_management/doctype/pledge/pledge.json
@@ -1,4 +1,5 @@
 {
+ "actions": [],
  "creation": "2019-09-09 17:06:16.756573",
  "doctype": "DocType",
  "editable_grid": 1,
@@ -49,7 +50,8 @@
    "fieldname": "qty",
    "fieldtype": "Float",
    "in_list_view": 1,
-   "label": "Quantity"
+   "label": "Quantity",
+   "non_negative": 1
   },
   {
    "fieldname": "loan_security_price",
@@ -86,7 +88,8 @@
   }
  ],
  "istable": 1,
- "modified": "2019-12-03 10:59:58.001421",
+ "links": [],
+ "modified": "2020-11-05 10:07:15.424937",
  "modified_by": "Administrator",
  "module": "Loan Management",
  "name": "Pledge",
diff --git a/erpnext/loan_management/doctype/process_loan_interest_accrual/process_loan_interest_accrual.json b/erpnext/loan_management/doctype/process_loan_interest_accrual/process_loan_interest_accrual.json
index 0ef098f..828df2e 100644
--- a/erpnext/loan_management/doctype/process_loan_interest_accrual/process_loan_interest_accrual.json
+++ b/erpnext/loan_management/doctype/process_loan_interest_accrual/process_loan_interest_accrual.json
@@ -10,6 +10,7 @@
   "loan_type",
   "loan",
   "process_type",
+  "accrual_type",
   "amended_from"
  ],
  "fields": [
@@ -47,17 +48,27 @@
    "hidden": 1,
    "label": "Process Type",
    "read_only": 1
+  },
+  {
+   "fieldname": "accrual_type",
+   "fieldtype": "Select",
+   "hidden": 1,
+   "label": "Accrual Type",
+   "options": "Regular\nRepayment\nDisbursement",
+   "read_only": 1
   }
  ],
+ "index_web_pages_for_search": 1,
  "is_submittable": 1,
  "links": [],
- "modified": "2020-04-09 22:52:53.911416",
+ "modified": "2020-11-06 13:28:51.478909",
  "modified_by": "Administrator",
  "module": "Loan Management",
  "name": "Process Loan Interest Accrual",
  "owner": "Administrator",
  "permissions": [
   {
+   "cancel": 1,
    "create": 1,
    "delete": 1,
    "email": 1,
@@ -67,9 +78,11 @@
    "report": 1,
    "role": "System Manager",
    "share": 1,
+   "submit": 1,
    "write": 1
   },
   {
+   "cancel": 1,
    "create": 1,
    "delete": 1,
    "email": 1,
@@ -79,6 +92,7 @@
    "report": 1,
    "role": "Loan Manager",
    "share": 1,
+   "submit": 1,
    "write": 1
   }
  ],
diff --git a/erpnext/loan_management/doctype/process_loan_interest_accrual/process_loan_interest_accrual.py b/erpnext/loan_management/doctype/process_loan_interest_accrual/process_loan_interest_accrual.py
index 0fa9686..11333dc 100644
--- a/erpnext/loan_management/doctype/process_loan_interest_accrual/process_loan_interest_accrual.py
+++ b/erpnext/loan_management/doctype/process_loan_interest_accrual/process_loan_interest_accrual.py
@@ -20,19 +20,20 @@
 
 		if (not self.loan or not loan_doc.is_term_loan) and self.process_type != 'Term Loans':
 			make_accrual_interest_entry_for_demand_loans(self.posting_date, self.name,
-				open_loans = open_loans, loan_type = self.loan_type)
+				open_loans = open_loans, loan_type = self.loan_type, accrual_type=self.accrual_type)
 
 		if (not self.loan or loan_doc.is_term_loan) and self.process_type != 'Demand Loans':
 			make_accrual_interest_entry_for_term_loans(self.posting_date, self.name, term_loan=self.loan,
-				loan_type=self.loan_type)
+				loan_type=self.loan_type, accrual_type=self.accrual_type)
 
 
-def process_loan_interest_accrual_for_demand_loans(posting_date=None, loan_type=None, loan=None):
+def process_loan_interest_accrual_for_demand_loans(posting_date=None, loan_type=None, loan=None, accrual_type="Regular"):
 	loan_process = frappe.new_doc('Process Loan Interest Accrual')
 	loan_process.posting_date = posting_date or nowdate()
 	loan_process.loan_type = loan_type
 	loan_process.process_type = 'Demand Loans'
 	loan_process.loan = loan
+	loan_process.accrual_type = accrual_type
 
 	loan_process.submit()
 
diff --git a/erpnext/loan_management/doctype/proposed_pledge/proposed_pledge.json b/erpnext/loan_management/doctype/proposed_pledge/proposed_pledge.json
index aee7c2c..3e7e778 100644
--- a/erpnext/loan_management/doctype/proposed_pledge/proposed_pledge.json
+++ b/erpnext/loan_management/doctype/proposed_pledge/proposed_pledge.json
@@ -1,4 +1,5 @@
 {
+ "actions": [],
  "creation": "2019-08-29 22:29:37.628178",
  "doctype": "DocType",
  "editable_grid": 1,
@@ -39,7 +40,8 @@
    "fieldname": "qty",
    "fieldtype": "Float",
    "in_list_view": 1,
-   "label": "Quantity"
+   "label": "Quantity",
+   "non_negative": 1
   },
   {
    "fieldname": "loan_security",
@@ -56,8 +58,10 @@
    "read_only": 1
   }
  ],
+ "index_web_pages_for_search": 1,
  "istable": 1,
- "modified": "2019-12-02 10:23:11.498308",
+ "links": [],
+ "modified": "2020-11-05 10:07:37.542344",
  "modified_by": "Administrator",
  "module": "Loan Management",
  "name": "Proposed Pledge",
diff --git a/erpnext/loan_management/doctype/unpledge/unpledge.json b/erpnext/loan_management/doctype/unpledge/unpledge.json
index ee192d7..0035668 100644
--- a/erpnext/loan_management/doctype/unpledge/unpledge.json
+++ b/erpnext/loan_management/doctype/unpledge/unpledge.json
@@ -52,6 +52,7 @@
    "fieldtype": "Float",
    "in_list_view": 1,
    "label": "Quantity",
+   "non_negative": 1,
    "reqd": 1
   },
   {
@@ -62,9 +63,10 @@
    "read_only": 1
   }
  ],
+ "index_web_pages_for_search": 1,
  "istable": 1,
  "links": [],
- "modified": "2020-05-06 10:50:18.448552",
+ "modified": "2020-11-05 10:07:28.106961",
  "modified_by": "Administrator",
  "module": "Loan Management",
  "name": "Unpledge",
diff --git a/erpnext/loan_management/loan_common.js b/erpnext/loan_management/loan_common.js
index d9dd415..50b68da 100644
--- a/erpnext/loan_management/loan_common.js
+++ b/erpnext/loan_management/loan_common.js
@@ -8,14 +8,14 @@
 			frm.refresh_field('applicant_type');
 		}
 
-		if (['Loan Disbursement', 'Loan Repayment', 'Loan Interest Accrual'].includes(frm.doc.doctype)
+		if (['Loan Disbursement', 'Loan Repayment', 'Loan Interest Accrual', 'Loan Write Off'].includes(frm.doc.doctype)
 			&& frm.doc.docstatus > 0) {
 
 			frm.add_custom_button(__("Accounting Ledger"), function() {
 				frappe.route_options = {
 					voucher_no: frm.doc.name,
 					company: frm.doc.company,
-					from_date: frm.doc.posting_date,
+					from_date: moment(frm.doc.posting_date).format('YYYY-MM-DD'),
 					to_date: moment(frm.doc.modified).format('YYYY-MM-DD'),
 					show_cancelled_entries: frm.doc.docstatus === 2
 				};
diff --git a/erpnext/maintenance/doctype/maintenance_schedule/maintenance_schedule.js b/erpnext/maintenance/doctype/maintenance_schedule/maintenance_schedule.js
index e940b60..ddbcdfd 100644
--- a/erpnext/maintenance/doctype/maintenance_schedule/maintenance_schedule.js
+++ b/erpnext/maintenance/doctype/maintenance_schedule/maintenance_schedule.js
@@ -66,7 +66,7 @@
 							company: me.frm.doc.company
 						}
 					});
-				}, __("Get items from"));
+				}, __("Get Items From"));
 		} else if (this.frm.doc.docstatus === 1) {
 			this.frm.add_custom_button(__('Create Maintenance Visit'), function() {
 				frappe.model.open_mapped_doc({
diff --git a/erpnext/maintenance/doctype/maintenance_visit/maintenance_visit.js b/erpnext/maintenance/doctype/maintenance_visit/maintenance_visit.js
index 2e2a9ce..4cbb02a 100644
--- a/erpnext/maintenance/doctype/maintenance_visit/maintenance_visit.js
+++ b/erpnext/maintenance/doctype/maintenance_visit/maintenance_visit.js
@@ -62,7 +62,7 @@
 							company: me.frm.doc.company
 						}
 					})
-				}, __("Get items from"));
+				}, __("Get Items From"));
 			this.frm.add_custom_button(__('Warranty Claim'),
 				function() {
 					erpnext.utils.map_current_doc({
@@ -78,7 +78,7 @@
 							company: me.frm.doc.company
 						}
 					})
-				}, __("Get items from"));
+				}, __("Get Items From"));
 			this.frm.add_custom_button(__('Sales Order'),
 				function() {
 					erpnext.utils.map_current_doc({
@@ -94,7 +94,7 @@
 							order_type: me.frm.doc.order_type,
 						}
 					})
-				}, __("Get items from"));
+				}, __("Get Items From"));
 		}
 	},
 });
diff --git a/erpnext/manufacturing/doctype/bom/bom.py b/erpnext/manufacturing/doctype/bom/bom.py
index 2ab1b98..8888a96 100644
--- a/erpnext/manufacturing/doctype/bom/bom.py
+++ b/erpnext/manufacturing/doctype/bom/bom.py
@@ -76,6 +76,7 @@
 		self.set_routing_operations()
 		self.validate_operations()
 		self.calculate_cost()
+		self.update_stock_qty()
 		self.update_cost(update_parent=False, from_child_bom=True, save=False)
 
 	def get_context(self, context):
@@ -84,8 +85,6 @@
 	def on_update(self):
 		frappe.cache().hdel('bom_children', self.name)
 		self.check_recursion()
-		self.update_stock_qty()
-		self.update_exploded_items()
 
 	def on_submit(self):
 		self.manage_default_bom()
@@ -237,7 +236,8 @@
 			self.calculate_cost()
 		if save:
 			self.db_update()
-		self.update_exploded_items()
+
+		self.update_exploded_items(save=save)
 
 		# update parent BOMs
 		if self.total_cost != existing_bom_cost and update_parent:
@@ -318,8 +318,6 @@
 				m.uom = m.stock_uom
 				m.qty = m.stock_qty
 
-			m.db_update()
-
 	def validate_uom_is_interger(self):
 		from erpnext.utilities.transaction_base import validate_uom_is_integer
 		validate_uom_is_integer(self, "uom", "qty", "BOM Item")
@@ -372,15 +370,6 @@
 		if raise_exception:
 			frappe.throw(_("BOM recursion: {0} cannot be parent or child of {1}").format(self.name, self.name))
 
-	def update_cost_and_exploded_items(self, bom_list=[]):
-		bom_list = self.traverse_tree(bom_list)
-		for bom in bom_list:
-			bom_obj = frappe.get_doc("BOM", bom)
-			bom_obj.check_recursion(bom_list=bom_list)
-			bom_obj.update_exploded_items()
-
-		return bom_list
-
 	def traverse_tree(self, bom_list=None):
 		def _get_children(bom_no):
 			children = frappe.cache().hget('bom_children', bom_no)
@@ -472,10 +461,10 @@
 			d.rate = rate
 			d.amount = (d.stock_qty or d.qty) * rate
 
-	def update_exploded_items(self):
+	def update_exploded_items(self, save=True):
 		""" Update Flat BOM, following will be correct data"""
 		self.get_exploded_items()
-		self.add_exploded_items()
+		self.add_exploded_items(save=save)
 
 	def get_exploded_items(self):
 		""" Get all raw materials including items from child bom"""
@@ -544,11 +533,13 @@
 				'sourced_by_supplier': d.get('sourced_by_supplier', 0)
 			}))
 
-	def add_exploded_items(self):
+	def add_exploded_items(self, save=True):
 		"Add items to Flat BOM table"
-		frappe.db.sql("""delete from `tabBOM Explosion Item` where parent=%s""", self.name)
 		self.set('exploded_items', [])
 
+		if save:
+			frappe.db.sql("""delete from `tabBOM Explosion Item` where parent=%s""", self.name)
+
 		for d in sorted(self.cur_exploded_items, key=itemgetter(0)):
 			ch = self.append('exploded_items', {})
 			for i in self.cur_exploded_items[d].keys():
@@ -556,7 +547,9 @@
 			ch.amount = flt(ch.stock_qty) * flt(ch.rate)
 			ch.qty_consumed_per_unit = flt(ch.stock_qty) / flt(self.quantity)
 			ch.docstatus = self.docstatus
-			ch.db_insert()
+
+			if save:
+				ch.db_insert()
 
 	def validate_bom_links(self):
 		if not self.is_active:
diff --git a/erpnext/manufacturing/doctype/job_card/job_card.js b/erpnext/manufacturing/doctype/job_card/job_card.js
index b051b32..4e8dd41 100644
--- a/erpnext/manufacturing/doctype/job_card/job_card.js
+++ b/erpnext/manufacturing/doctype/job_card/job_card.js
@@ -31,6 +31,16 @@
 			}
 		}
 
+		frm.set_query("quality_inspection", function() {
+			return {
+				query: "erpnext.stock.doctype.quality_inspection.quality_inspection.quality_inspection_query",
+				filters: {
+					"item_code": frm.doc.production_item,
+					"reference_name": frm.doc.name
+				}
+			};
+		});
+
 		frm.trigger("toggle_operation_number");
 
 		if (frm.doc.docstatus == 0 && (frm.doc.for_quantity > frm.doc.total_completed_qty || !frm.doc.for_quantity)
diff --git a/erpnext/manufacturing/doctype/job_card/job_card.json b/erpnext/manufacturing/doctype/job_card/job_card.json
index 575e719..5713f69 100644
--- a/erpnext/manufacturing/doctype/job_card/job_card.json
+++ b/erpnext/manufacturing/doctype/job_card/job_card.json
@@ -20,6 +20,7 @@
   "production_item",
   "item_name",
   "for_quantity",
+  "quality_inspection",
   "wip_warehouse",
   "column_break_12",
   "employee",
@@ -305,11 +306,19 @@
    "label": "Sequence Id",
    "print_hide": 1,
    "read_only": 1
+  },
+  {
+   "depends_on": "eval:!doc.__islocal;",
+   "fieldname": "quality_inspection",
+   "fieldtype": "Link",
+   "label": "Quality Inspection",
+   "no_copy": 1,
+   "options": "Quality Inspection"
   }
  ],
  "is_submittable": 1,
  "links": [],
- "modified": "2020-10-14 12:58:25.327897",
+ "modified": "2020-11-19 18:26:50.531664",
  "modified_by": "Administrator",
  "module": "Manufacturing",
  "name": "Job Card",
diff --git a/erpnext/manufacturing/doctype/job_card/job_card.py b/erpnext/manufacturing/doctype/job_card/job_card.py
index 4dfa78b..d15d81e 100644
--- a/erpnext/manufacturing/doctype/job_card/job_card.py
+++ b/erpnext/manufacturing/doctype/job_card/job_card.py
@@ -353,17 +353,19 @@
 
 @frappe.whitelist()
 def get_operations(doctype, txt, searchfield, start, page_len, filters):
-	if filters.get("work_order"):
-		args = {"parent": filters.get("work_order")}
-		if txt:
-			args["operation"] = ("like", "%{0}%".format(txt))
+	if not filters.get("work_order"):
+		frappe.msgprint(_("Please select a Work Order first."))
+		return []
+	args = {"parent": filters.get("work_order")}
+	if txt:
+		args["operation"] = ("like", "%{0}%".format(txt))
 
-		return frappe.get_all("Work Order Operation",
-			filters = args,
-			fields = ["distinct operation as operation"],
-			limit_start = start,
-			limit_page_length = page_len,
-			order_by="idx asc", as_list=1)
+	return frappe.get_all("Work Order Operation",
+		filters = args,
+		fields = ["distinct operation as operation"],
+		limit_start = start,
+		limit_page_length = page_len,
+		order_by="idx asc", as_list=1)
 
 @frappe.whitelist()
 def make_material_request(source_name, target_doc=None):
diff --git a/erpnext/manufacturing/doctype/production_plan/production_plan.json b/erpnext/manufacturing/doctype/production_plan/production_plan.json
index 850d5ae..7daf706 100644
--- a/erpnext/manufacturing/doctype/production_plan/production_plan.json
+++ b/erpnext/manufacturing/doctype/production_plan/production_plan.json
@@ -19,6 +19,7 @@
   "column_break2",
   "from_date",
   "to_date",
+  "sales_order_status",
   "sales_orders_detail",
   "get_sales_orders",
   "sales_orders",
@@ -301,13 +302,20 @@
    "label": "Warehouses",
    "options": "Production Plan Material Request Warehouse",
    "read_only": 1
+  },
+  {
+   "depends_on": "eval: doc.get_items_from == \"Sales Order\"",
+   "fieldname": "sales_order_status",
+   "fieldtype": "Select",
+   "label": "Sales Order Status",
+   "options": "\nTo Deliver and Bill\nTo Bill\nTo Deliver"
   }
  ],
  "icon": "fa fa-calendar",
  "index_web_pages_for_search": 1,
  "is_submittable": 1,
  "links": [],
- "modified": "2020-10-26 13:00:54.335319",
+ "modified": "2020-11-10 18:01:54.991970",
  "modified_by": "Administrator",
  "module": "Manufacturing",
  "name": "Production Plan",
diff --git a/erpnext/manufacturing/doctype/production_plan/production_plan.py b/erpnext/manufacturing/doctype/production_plan/production_plan.py
index a314a15..3833e86 100644
--- a/erpnext/manufacturing/doctype/production_plan/production_plan.py
+++ b/erpnext/manufacturing/doctype/production_plan/production_plan.py
@@ -571,6 +571,8 @@
 		so_filter += " and so.customer = %(customer)s"
 	if self.project:
 		so_filter += " and so.project = %(project)s"
+	if self.sales_order_status:
+		so_filter += "and so.status = %(sales_order_status)s"
 
 	if self.item_code:
 		item_filter += " and so_item.item_code = %(item)s"
@@ -594,8 +596,8 @@
 			"customer": self.customer,
 			"project": self.project,
 			"item": self.item_code,
-			"company": self.company
-
+			"company": self.company,
+			"sales_order_status": self.sales_order_status
 		}, as_dict=1)
 	return open_so
 
diff --git a/erpnext/manufacturing/doctype/production_plan/test_production_plan.py b/erpnext/manufacturing/doctype/production_plan/test_production_plan.py
index fa9d080..27335aa 100644
--- a/erpnext/manufacturing/doctype/production_plan/test_production_plan.py
+++ b/erpnext/manufacturing/doctype/production_plan/test_production_plan.py
@@ -137,7 +137,8 @@
 			'from_date': so.transaction_date,
 			'to_date': so.transaction_date,
 			'customer': so.customer,
-			'item_code': item
+			'item_code': item,
+			'sales_order_status': so.status
 		})
 		sales_orders = get_sales_orders(pln) or {}
 		sales_orders = [d.get('name') for d in sales_orders if d.get('name') == sales_order]
diff --git a/erpnext/manufacturing/doctype/work_order/test_work_order.py b/erpnext/manufacturing/doctype/work_order/test_work_order.py
index 5f8a134..e539279 100644
--- a/erpnext/manufacturing/doctype/work_order/test_work_order.py
+++ b/erpnext/manufacturing/doctype/work_order/test_work_order.py
@@ -443,6 +443,11 @@
 		ste1 = frappe.get_doc(make_stock_entry(wo.name, "Manufacture", 1))
 		self.assertEqual(len(ste1.items), 3)
 
+	def test_cost_center_for_manufacture(self):
+		wo_order = make_wo_order_test_record()
+		ste = make_stock_entry(wo_order.name, "Material Transfer for Manufacture", wo_order.qty)
+		self.assertEquals(ste.get("items")[0].get("cost_center"), "_Test Cost Center - _TC")
+
 	def test_operation_time_with_batch_size(self):
 		fg_item = "Test Batch Size Item For BOM"
 		rm1 = "Test Batch Size Item RM 1 For BOM"
diff --git a/erpnext/manufacturing/report/bom_stock_report/bom_stock_report.js b/erpnext/manufacturing/report/bom_stock_report/bom_stock_report.js
index 2ac6fa0..8cd0164 100644
--- a/erpnext/manufacturing/report/bom_stock_report/bom_stock_report.js
+++ b/erpnext/manufacturing/report/bom_stock_report/bom_stock_report.js
@@ -25,11 +25,11 @@
 	],
 	"formatter": function(value, row, column, data, default_formatter) {
 		value = default_formatter(value, row, column, data);
-		if (column.id == "Item"){
-			if (data["Enough Parts to Build"] > 0){
-				value = `<a style='color:green' href="#Form/Item/${data['Item']}" data-doctype="Item">${data['Item']}</a>`
+		if (column.id == "item") {
+			if (data["enough_parts_to_build"] > 0) {
+				value = `<a style='color:green' href="#Form/Item/${data['item']}" data-doctype="Item">${data['item']}</a>`;
 			} else {
-				value = `<a style='color:red' href="#Form/Item/${data['Item']}" data-doctype="Item">${data['Item']}</a>`
+				value = `<a style='color:red' href="#Form/Item/${data['item']}" data-doctype="Item">${data['item']}</a>`;
 			}
 		}
 		return value
diff --git a/erpnext/non_profit/doctype/membership/membership.py b/erpnext/non_profit/doctype/membership/membership.py
index 4c85cb6..7d15aba 100644
--- a/erpnext/non_profit/doctype/membership/membership.py
+++ b/erpnext/non_profit/doctype/membership/membership.py
@@ -70,7 +70,7 @@
 		settings = frappe.get_doc("Membership Settings")
 
 		if not member.customer:
-			frappe.throw(_("No customer linked to member {}", [member.name]))
+			frappe.throw(_("No customer linked to member {0}").format(frappe.bold(self.member)))
 
 		if not settings.debit_account:
 			frappe.throw(_("You need to set <b>Debit Account</b> in Membership Settings"))
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index 34dbdd0..98b2fcd 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -733,4 +733,6 @@
 erpnext.patches.v13_0.set_payment_channel_in_payment_gateway_account
 erpnext.patches.v13_0.create_healthcare_custom_fields_in_stock_entry_detail
 erpnext.patches.v13_0.update_reason_for_resignation_in_employee
-execute:frappe.delete_doc("Report", "Quoted Item Comparison")
\ No newline at end of file
+erpnext.patches.v13_0.update_custom_fields_for_shopify
+execute:frappe.delete_doc("Report", "Quoted Item Comparison")
+erpnext.patches.v13_0.create_leave_policy_assignment_based_on_employee_current_leave_policy
diff --git a/erpnext/patches/v12_0/generate_leave_ledger_entries.py b/erpnext/patches/v12_0/generate_leave_ledger_entries.py
index 7afde37..fe072d7 100644
--- a/erpnext/patches/v12_0/generate_leave_ledger_entries.py
+++ b/erpnext/patches/v12_0/generate_leave_ledger_entries.py
@@ -51,7 +51,7 @@
 
 	for encashment in leave_encashments:
 		if not frappe.db.exists("Leave Ledger Entry", {'transaction_type': 'Leave Encashment', 'transaction_name': encashment.name}):
-			frappe.get_doc("Leave Enchashment", encashment).create_leave_ledger_entry()
+			frappe.get_doc("Leave Encashment", encashment).create_leave_ledger_entry()
 
 def generate_expiry_allocation_ledger_entries():
 	''' fix ledger entries for missing leave allocation transaction '''
diff --git a/erpnext/patches/v13_0/create_leave_policy_assignment_based_on_employee_current_leave_policy.py b/erpnext/patches/v13_0/create_leave_policy_assignment_based_on_employee_current_leave_policy.py
new file mode 100644
index 0000000..80c9137
--- /dev/null
+++ b/erpnext/patches/v13_0/create_leave_policy_assignment_based_on_employee_current_leave_policy.py
@@ -0,0 +1,77 @@
+# Copyright (c) 2019, Frappe and Contributors
+# License: GNU General Public License v3. See license.txt
+
+from __future__ import unicode_literals
+
+import frappe
+
+def execute():
+    if "leave_policy" in frappe.db.get_table_columns("Employee"):
+        employees_with_leave_policy = frappe.db.sql("SELECT name, leave_policy FROM `tabEmployee` WHERE leave_policy IS NOT NULL and leave_policy != ''", as_dict = 1)
+
+        employee_with_assignment = []
+        leave_policy =[]
+
+        #for employee
+
+        for employee in employees_with_leave_policy:
+            alloc = frappe.db.exists("Leave Allocation", {"employee":employee.name, "leave_policy": employee.leave_policy, "docstatus": 1})
+            if not alloc:
+                create_assignment(employee.name, employee.leave_policy)
+
+            employee_with_assignment.append(employee.name)
+            leave_policy.append(employee.leave_policy)
+
+
+    if "default_leave_policy" in frappe.db.get_table_columns("Employee"):
+        employee_grade_with_leave_policy = frappe.db.sql("SELECT name, default_leave_policy FROM `tabEmployee Grade` WHERE default_leave_policy IS NOT NULL and default_leave_policy!=''", as_dict = 1)
+
+        #for whole employee Grade
+
+        for grade in employee_grade_with_leave_policy:
+            employees = get_employee_with_grade(grade.name)
+            for employee in employees:
+
+                if employee not in employee_with_assignment: #Will ensure no duplicate
+                    alloc = frappe.db.exists("Leave Allocation", {"employee":employee.name, "leave_policy": grade.default_leave_policy, "docstatus": 1})
+                    if not alloc:
+                        create_assignment(employee.name, grade.default_leave_policy)
+                    leave_policy.append(grade.default_leave_policy)
+
+    #for old Leave allocation and leave policy from allocation, which may got updated in employee grade.
+    leave_allocations = frappe.db.sql("SELECT leave_policy, leave_period, employee FROM `tabLeave Allocation` WHERE leave_policy IS NOT NULL and leave_policy != '' and docstatus = 1 ", as_dict = 1)
+
+    for allocation in leave_allocations:
+        if allocation.leave_policy not in leave_policy:
+            create_assignment(allocation.employee, allocation.leave_policy, leave_period=allocation.leave_period,
+                allocation_exists=True)
+
+def create_assignment(employee, leave_policy, leave_period=None, allocation_exists = False):
+
+    filters = {"employee":employee, "leave_policy": leave_policy}
+    if leave_period:
+        filters["leave_period"] = leave_period
+
+    if not frappe.db.exists("Leave Policy Assignment" , filters):
+        lpa = frappe.new_doc("Leave Policy Assignment")
+        lpa.employee = employee
+        lpa.leave_policy = leave_policy
+
+        lpa.flags.ignore_mandatory = True
+        if allocation_exists:
+            lpa.assignment_based_on = 'Leave Period'
+            lpa.leave_period = leave_period
+            lpa.leaves_allocated = 1
+
+        lpa.save()
+        if allocation_exists:
+            lpa.submit()
+            #Updating old Leave Allocation
+            frappe.db.sql("Update `tabLeave Allocation` set leave_policy_assignment = %s", lpa.name)
+
+
+def get_employee_with_grade(grade):
+    return frappe.get_list("Employee", filters = {"grade": grade})
+
+
+
diff --git a/erpnext/patches/v13_0/update_custom_fields_for_shopify.py b/erpnext/patches/v13_0/update_custom_fields_for_shopify.py
new file mode 100644
index 0000000..f1d2ea2
--- /dev/null
+++ b/erpnext/patches/v13_0/update_custom_fields_for_shopify.py
@@ -0,0 +1,10 @@
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
+# MIT License. See license.txt
+
+from __future__ import unicode_literals
+import frappe
+from erpnext.erpnext_integrations.doctype.shopify_settings.shopify_settings import setup_custom_fields
+
+def execute():
+	if frappe.db.get_single_value('Shopify Settings', 'enable_shopify'):
+		setup_custom_fields()
diff --git a/erpnext/payroll/doctype/payroll_entry/payroll_entry.py b/erpnext/payroll/doctype/payroll_entry/payroll_entry.py
index 30ea432..a3d12c3 100644
--- a/erpnext/payroll/doctype/payroll_entry/payroll_entry.py
+++ b/erpnext/payroll/doctype/payroll_entry/payroll_entry.py
@@ -344,9 +344,13 @@
 		employees_to_mark_attendance = []
 		days_in_payroll, days_holiday, days_attendance_marked = 0, 0, 0
 		for employee_detail in self.employees:
-			days_holiday = self.get_count_holidays_of_employee(employee_detail.employee)
-			days_attendance_marked = self.get_count_employee_attendance(employee_detail.employee)
-			days_in_payroll = date_diff(self.end_date, self.start_date) + 1
+			employee_joining_date = frappe.db.get_value("Employee", employee_detail.employee, 'date_of_joining')
+			start_date = self.start_date
+			if employee_joining_date > getdate(self.start_date):
+				start_date = employee_joining_date
+			days_holiday = self.get_count_holidays_of_employee(employee_detail.employee, start_date)
+			days_attendance_marked = self.get_count_employee_attendance(employee_detail.employee, start_date)
+			days_in_payroll = date_diff(self.end_date, start_date) + 1
 			if days_in_payroll > days_holiday + days_attendance_marked:
 				employees_to_mark_attendance.append({
 					"employee": employee_detail.employee,
@@ -354,22 +358,25 @@
 					})
 		return employees_to_mark_attendance
 
-	def get_count_holidays_of_employee(self, employee):
+	def get_count_holidays_of_employee(self, employee, start_date):
 		holiday_list = get_holiday_list_for_employee(employee)
 		holidays = 0
 		if holiday_list:
 			days = frappe.db.sql("""select count(*) from tabHoliday where
 				parent=%s and holiday_date between %s and %s""", (holiday_list,
-				self.start_date, self.end_date))
+				start_date, self.end_date))
 			if days and days[0][0]:
 				holidays = days[0][0]
 		return holidays
 
-	def get_count_employee_attendance(self, employee):
+	def get_count_employee_attendance(self, employee, start_date):
 		marked_days = 0
-		attendances = frappe.db.sql("""select count(*) from tabAttendance where
-			employee=%s and docstatus=1 and attendance_date between %s and %s""",
-			(employee, self.start_date, self.end_date))
+		attendances = frappe.get_all("Attendance",
+				fields = ["count(*)"],
+				filters = {
+					"employee": employee,
+					"attendance_date": ('between', [start_date, self.end_date])
+				}, as_list=1)
 		if attendances and attendances[0][0]:
 			marked_days = attendances[0][0]
 		return marked_days
diff --git a/erpnext/payroll/doctype/salary_slip/salary_slip.js b/erpnext/payroll/doctype/salary_slip/salary_slip.js
index 7b69dbe..0671b57 100644
--- a/erpnext/payroll/doctype/salary_slip/salary_slip.js
+++ b/erpnext/payroll/doctype/salary_slip/salary_slip.js
@@ -13,12 +13,12 @@
 			];
 		});
 
-		frm.fields_dict["timesheets"].grid.get_field("time_sheet").get_query = function(){
+		frm.fields_dict["timesheets"].grid.get_field("time_sheet").get_query = function() {
 			return {
 				filters: {
 					employee: frm.doc.employee
 				}
-			}
+			};
 		};
 
 		frm.set_query("salary_component", "earnings", function() {
@@ -26,7 +26,7 @@
 				filters: {
 					type: "earning"
 				}
-			}
+			};
 		});
 
 		frm.set_query("salary_component", "deductions", function() {
@@ -34,18 +34,18 @@
 				filters: {
 					type: "deduction"
 				}
-			}
+			};
 		});
 
 		frm.set_query("employee", function() {
-			return{
+			return {
 				query: "erpnext.controllers.queries.employee_query"
-			}
+			};
 		});
 	},
 
-	start_date: function(frm){
-		if(frm.doc.start_date){
+	start_date: function(frm) {
+		if (frm.doc.start_date) {
 			frm.trigger("set_end_date");
 		}
 	},
@@ -54,7 +54,7 @@
 		frm.events.get_emp_and_working_day_details(frm);
 	},
 
-	set_end_date: function(frm){
+	set_end_date: function(frm) {
 		frappe.call({
 			method: 'erpnext.payroll.doctype.payroll_entry.payroll_entry.get_end_date',
 			args: {
@@ -66,22 +66,22 @@
 					frm.set_value('end_date', r.message.end_date);
 				}
 			}
-		})
+		});
 	},
 
 	company: function(frm) {
 		var company = locals[':Company'][frm.doc.company];
-		if(!frm.doc.letter_head && company.default_letter_head) {
+		if (!frm.doc.letter_head && company.default_letter_head) {
 			frm.set_value('letter_head', company.default_letter_head);
 		}
 	},
 
 	refresh: function(frm) {
-		frm.trigger("toggle_fields")
+		frm.trigger("toggle_fields");
 
 		var salary_detail_fields = ["formula", "abbr", "statistical_component", "variable_based_on_taxable_salary"];
-		cur_frm.fields_dict['earnings'].grid.set_column_disp(salary_detail_fields,false);
-		cur_frm.fields_dict['deductions'].grid.set_column_disp(salary_detail_fields,false);
+		cur_frm.fields_dict['earnings'].grid.set_column_disp(salary_detail_fields, false);
+		cur_frm.fields_dict['deductions'].grid.set_column_disp(salary_detail_fields, false);
 	},
 
 	salary_slip_based_on_timesheet: function(frm) {
@@ -98,12 +98,12 @@
 		frm.events.get_emp_and_working_day_details(frm);
 	},
 
-	leave_without_pay: function(frm){
+	leave_without_pay: function(frm) {
 		if (frm.doc.employee && frm.doc.start_date && frm.doc.end_date) {
 			return frappe.call({
 				method: 'process_salary_based_on_working_days',
 				doc: frm.doc,
-				callback: function(r, rt) {
+				callback: function() {
 					frm.refresh();
 				}
 			});
@@ -121,10 +121,10 @@
 		return frappe.call({
 			method: 'get_emp_and_working_day_details',
 			doc: frm.doc,
-			callback: function(r, rt) {
+			callback: function(r) {
 				frm.refresh();
-				if (r.message){
-					frm.fields_dict.absent_days.set_description("Unmarked Days is treated as "+ r.message +". You can can change this in " + frappe.utils.get_form_link("Payroll Settings", "Payroll Settings", true));
+				if (r.message[1] !== "Leave" && r.message[0]) {
+					frm.fields_dict.absent_days.set_description(__("Unmarked Days is treated as ")+ r.message[0] +__(". You can can change this in ") + frappe.utils.get_form_link("Payroll Settings", "Payroll Settings", true));
 				}
 			}
 		});
@@ -141,7 +141,7 @@
 });
 
 // calculate total working hours, earnings based on hourly wages and totals
-var total_work_hours = function(frm, dt, dn) {
+var total_work_hours = function(frm) {
 	var total_working_hours = 0.0;
 	$.each(frm.doc["timesheets"] || [], function(i, timesheet) {
 		total_working_hours += timesheet.working_hours;
@@ -165,4 +165,4 @@
 		frm.doc.rounded_total = Math.round(frm.doc.net_pay);
 		refresh_many(['net_pay', 'rounded_total']);
 	});
-}
+};
diff --git a/erpnext/payroll/doctype/salary_slip/salary_slip.py b/erpnext/payroll/doctype/salary_slip/salary_slip.py
index 4ccf564..7b87ae5 100644
--- a/erpnext/payroll/doctype/salary_slip/salary_slip.py
+++ b/erpnext/payroll/doctype/salary_slip/salary_slip.py
@@ -136,8 +136,8 @@
 				self.salary_slip_based_on_timesheet = self._salary_structure_doc.salary_slip_based_on_timesheet or 0
 				self.set_time_sheet()
 				self.pull_sal_struct()
-				consider_unmarked_attendance_as = frappe.db.get_value("Payroll Settings", None, "consider_unmarked_attendance_as") or "Present"
-				return consider_unmarked_attendance_as
+				payroll_based_on, consider_unmarked_attendance_as = frappe.db.get_value("Payroll Settings", None, ["payroll_based_on","consider_unmarked_attendance_as"])
+				return [payroll_based_on, consider_unmarked_attendance_as]
 
 	def set_time_sheet(self):
 		if self.salary_slip_based_on_timesheet:
@@ -210,10 +210,10 @@
 			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)
+			actual_lwp, absent = self.calculate_lwp_ppl_and_absent_days_based_on_attendance(holidays)
 			self.absent_days = absent
 		else:
-			actual_lwp = self.calculate_lwp_based_on_leave_application(holidays, working_days)
+			actual_lwp = self.calculate_lwp_or_ppl_based_on_leave_application(holidays, working_days)
 
 		if not lwp:
 			lwp = actual_lwp
@@ -240,7 +240,6 @@
 				self.absent_days += unmarked_days #will be treated as absent
 				self.payment_days -= unmarked_days
 				if include_holidays_in_total_working_days:
-					self.absent_days -= len(holidays)
 					for holiday in holidays:
 						if not frappe.db.exists("Attendance", {"employee": self.employee, "attendance_date": holiday, "docstatus": 1 }):
 							self.payment_days += 1
@@ -301,7 +300,7 @@
 
 		return holidays
 
-	def calculate_lwp_based_on_leave_application(self, holidays, working_days):
+	def calculate_lwp_or_ppl_based_on_leave_application(self, holidays, working_days):
 		lwp = 0
 		holidays = "','".join(holidays)
 		daily_wages_fraction_for_half_day = \
@@ -312,10 +311,12 @@
 			leave = frappe.db.sql("""
 				SELECT t1.name,
 					CASE WHEN (t1.half_day_date = %(dt)s or t1.to_date = t1.from_date)
-					THEN t1.half_day else 0 END
+					THEN t1.half_day else 0 END,
+					t2.is_ppl,
+					t2.fraction_of_daily_salary_per_leave
 				FROM `tabLeave Application` t1, `tabLeave Type` t2
 				WHERE t2.name = t1.leave_type
-				AND t2.is_lwp = 1
+				AND (t2.is_lwp = 1 or t2.is_ppl = 1)
 				AND t1.docstatus = 1
 				AND t1.employee = %(employee)s
 				AND ifnull(t1.salary_slip, '') = ''
@@ -328,19 +329,35 @@
 				""".format(holidays), {"employee": self.employee, "dt": dt})
 
 			if leave:
+				equivalent_lwp_count = 0
 				is_half_day_leave = cint(leave[0][1])
-				lwp += (1 - daily_wages_fraction_for_half_day) if is_half_day_leave else 1
+				is_partially_paid_leave = cint(leave[0][2])
+				fraction_of_daily_salary_per_leave = flt(leave[0][3])
+
+				equivalent_lwp_count =  (1 - daily_wages_fraction_for_half_day) if is_half_day_leave else 1
+
+				if is_partially_paid_leave:
+					equivalent_lwp_count *= fraction_of_daily_salary_per_leave if fraction_of_daily_salary_per_leave else 1
+
+				lwp += equivalent_lwp_count
 
 		return lwp
 
-	def calculate_lwp_and_absent_days_based_on_attendance(self, holidays):
+	def calculate_lwp_ppl_and_absent_days_based_on_attendance(self, holidays):
 		lwp = 0
 		absent = 0
 
 		daily_wages_fraction_for_half_day = \
 			flt(frappe.db.get_value("Payroll Settings", None, "daily_wages_fraction_for_half_day")) or 0.5
 
-		lwp_leave_types = dict(frappe.get_all("Leave Type", {"is_lwp": 1}, ["name", "include_holiday"], as_list=1))
+		leave_types = frappe.get_all("Leave Type",
+			or_filters=[["is_ppl", "=", 1], ["is_lwp", "=", 1]],
+			fields =["name", "is_lwp", "is_ppl", "fraction_of_daily_salary_per_leave", "include_holiday"])
+
+		leave_type_map = {}
+		for leave_type in leave_types:
+			leave_type_map[leave_type.name] = leave_type
+
 		attendances = frappe.db.sql('''
 			SELECT attendance_date, status, leave_type
 			FROM `tabAttendance`
@@ -352,21 +369,30 @@
 		''', values=(self.employee, self.start_date, self.end_date), as_dict=1)
 
 		for d in attendances:
-			if d.status in ('Half Day', 'On Leave') and d.leave_type and d.leave_type not in lwp_leave_types:
+			if d.status in ('Half Day', 'On Leave') and d.leave_type and d.leave_type not in leave_type_map.keys():
 				continue
 
 			if formatdate(d.attendance_date, "yyyy-mm-dd") in holidays:
 				if d.status == "Absent" or \
-					(d.leave_type and d.leave_type in lwp_leave_types and not lwp_leave_types[d.leave_type]):
+					(d.leave_type and d.leave_type in leave_type_map.keys() and not leave_type_map[d.leave_type]['include_holiday']):
 						continue
 
+			if d.leave_type:
+				fraction_of_daily_salary_per_leave = leave_type_map[d.leave_type]["fraction_of_daily_salary_per_leave"]
+
 			if d.status == "Half Day":
-				lwp += (1 - daily_wages_fraction_for_half_day)
-			elif d.status == "On Leave" and d.leave_type in lwp_leave_types:
-				lwp += 1
+				equivalent_lwp =  (1 - daily_wages_fraction_for_half_day)
+
+				if d.leave_type in leave_type_map.keys() and leave_type_map[d.leave_type]["is_ppl"]:
+					equivalent_lwp *= fraction_of_daily_salary_per_leave if fraction_of_daily_salary_per_leave else 1
+				lwp += equivalent_lwp
+			elif d.status == "On Leave" and d.leave_type and d.leave_type in leave_type_map.keys():
+				equivalent_lwp = 1
+				if leave_type_map[d.leave_type]["is_ppl"]:
+					equivalent_lwp *= fraction_of_daily_salary_per_leave if fraction_of_daily_salary_per_leave else 1
+				lwp += equivalent_lwp
 			elif d.status == "Absent":
 				absent += 1
-
 		return lwp, absent
 
 	def add_earning_for_hourly_wages(self, doc, salary_component, amount):
@@ -950,9 +976,8 @@
 			amounts = calculate_amounts(payment.loan, self.posting_date, "Regular Payment")
 			total_amount = amounts['interest_amount'] + amounts['payable_principal_amount']
 			if payment.total_payment > total_amount:
-				frappe.throw(_("""Row {0}: Paid amount {1} is greater than pending accrued amount {2}
-					against loan {3}""").format(payment.idx, frappe.bold(payment.total_payment),
-					frappe.bold(total_amount), frappe.bold(payment.loan)))
+				frappe.throw(_("Row {0}: Paid amount {1} is greater than pending accrued amount {2}against loan {3}").format(
+					payment.idx, frappe.bold(payment.total_payment),frappe.bold(total_amount), frappe.bold(payment.loan)))
 
 			self.total_interest_amount += payment.interest_amount
 			self.total_principal_amount += payment.principal_amount
diff --git a/erpnext/payroll/doctype/salary_slip/test_salary_slip.py b/erpnext/payroll/doctype/salary_slip/test_salary_slip.py
index 7fe4165..e08dc7c 100644
--- a/erpnext/payroll/doctype/salary_slip/test_salary_slip.py
+++ b/erpnext/payroll/doctype/salary_slip/test_salary_slip.py
@@ -13,6 +13,8 @@
 from erpnext.payroll.doctype.salary_structure.salary_structure import make_salary_slip
 from erpnext.payroll.doctype.payroll_entry.payroll_entry import get_month_details
 from erpnext.hr.doctype.employee.test_employee import make_employee
+from erpnext.hr.doctype.leave_allocation.test_leave_allocation import create_leave_allocation
+from erpnext.hr.doctype.leave_type.test_leave_type import create_leave_type
 from erpnext.payroll.doctype.employee_tax_exemption_declaration.test_employee_tax_exemption_declaration \
 	import create_payroll_period, create_exemption_category
 
@@ -93,14 +95,27 @@
 
 		make_leave_application(emp_id, first_sunday, add_days(first_sunday, 3), "Leave Without Pay")
 
+		leave_type_ppl = create_leave_type(leave_type_name="Test Partially Paid Leave", is_ppl = 1)
+		leave_type_ppl.save()
+
+		alloc = create_leave_allocation(
+			employee = emp_id, from_date = add_days(first_sunday, 4),
+			to_date = add_days(first_sunday, 10), new_leaves_allocated = 3,
+			leave_type = "Test Partially Paid Leave")
+		alloc.save()
+		alloc.submit()
+
+		#two day leave ppl with fraction_of_daily_salary_per_leave = 0.5 equivalent to single day lwp
+		make_leave_application(emp_id, add_days(first_sunday, 4), add_days(first_sunday, 5), "Test Partially Paid Leave")
+
 		ss = make_employee_salary_slip("test_for_attendance@salary.com", "Monthly")
 
-		self.assertEqual(ss.leave_without_pay, 3)
+		self.assertEqual(ss.leave_without_pay, 4)
 
 		days_in_month = no_of_days[0]
 		no_of_holidays = no_of_days[1]
 
-		self.assertEqual(ss.payment_days, days_in_month - no_of_holidays - 3)
+		self.assertEqual(ss.payment_days, days_in_month - no_of_holidays - 4)
 
 		#Gross pay calculation based on attendances
 		gross_pay = 78000 - ((78000 / (days_in_month - no_of_holidays)) * flt(ss.leave_without_pay))
diff --git a/erpnext/payroll/report/bank_remittance/bank_remittance.py b/erpnext/payroll/report/bank_remittance/bank_remittance.py
index 4b052bf..500543c 100644
--- a/erpnext/payroll/report/bank_remittance/bank_remittance.py
+++ b/erpnext/payroll/report/bank_remittance/bank_remittance.py
@@ -47,33 +47,39 @@
 			"fieldtype": "Int",
 			"fieldname": "employee_account_no",
 			"width": 50
-		},
-		{
+		}
+	]
+
+	if frappe.db.has_column('Employee', 'ifsc_code'):
+		columns.append({
 			"label": _("IFSC Code"),
 			"fieldtype": "Data",
 			"fieldname": "bank_code",
 			"width": 100
-		},
-		{
-			"label": _("Currency"),
-			"fieldtype": "Data",
-			"fieldname": "currency",
-			"width": 50
-		},
-		{
-			"label": _("Net Salary Amount"),
-			"fieldtype": "Currency",
-			"options": "currency",
-			"fieldname": "amount",
-			"width": 100
-		}
-	]
+		})
+
+	columns += [{
+		"label": _("Currency"),
+		"fieldtype": "Data",
+		"fieldname": "currency",
+		"width": 50
+	},
+	{
+		"label": _("Net Salary Amount"),
+		"fieldtype": "Currency",
+		"options": "currency",
+		"fieldname": "amount",
+		"width": 100
+	}]
+
 	data = []
 
 	accounts = get_bank_accounts()
 	payroll_entries = get_payroll_entries(accounts, filters)
 	salary_slips = get_salary_slips(payroll_entries)
-	get_emp_bank_ifsc_code(salary_slips)
+
+	if frappe.db.has_column('Employee', 'ifsc_code'):
+		get_emp_bank_ifsc_code(salary_slips)
 
 	for salary in salary_slips:
 		if salary.bank_name and salary.bank_account_no and salary.debit_acc_no and salary.status in ["Submitted", "Paid"]:
diff --git a/erpnext/projects/doctype/task/task.js b/erpnext/projects/doctype/task/task.js
index 8c6a9cf..002ddb2 100644
--- a/erpnext/projects/doctype/task/task.js
+++ b/erpnext/projects/doctype/task/task.js
@@ -49,7 +49,10 @@
 			},
 			callback: function (r) {
 				if (r.message.length > 0) {
-					frappe.msgprint(__(`Cannot convert it to non-group. The following child Tasks exist: ${r.message.join(", ")}.`));
+					let message = __('Cannot convert Task to non-group because the following child Tasks exist: {0}.',
+						[r.message.join(", ")]
+					);
+					frappe.msgprint(message);
 					frm.reload_doc();
 				}
 			}
diff --git a/erpnext/projects/doctype/timesheet/timesheet.js b/erpnext/projects/doctype/timesheet/timesheet.js
index 607c3fd..b068245 100644
--- a/erpnext/projects/doctype/timesheet/timesheet.js
+++ b/erpnext/projects/doctype/timesheet/timesheet.js
@@ -133,6 +133,11 @@
 			frm: frm
 		});
 	},
+
+	project: function(frm) {
+		set_project_in_timelog(frm);
+	},
+
 });
 
 frappe.ui.form.on("Timesheet Detail", {
@@ -162,7 +167,11 @@
 		frappe.model.set_value(cdt, cdn, "hours", hours);
 	},
 
-	time_logs_add: function(frm) {
+	time_logs_add: function(frm, cdt, cdn) {
+		if(frm.doc.project) {
+			frappe.model.set_value(cdt, cdn, 'project', frm.doc.project);
+		}
+
 		var $trigger_again = $('.form-grid').find('.grid-row').find('.btn-open-row');
 		$trigger_again.on('click', () => {
 			$('.form-grid')
@@ -297,3 +306,9 @@
 		}
 	});
 };
+
+function set_project_in_timelog(frm) {
+	if(frm.doc.project){
+		erpnext.utils.copy_value_in_all_rows(frm.doc, frm.doc.doctype, frm.doc.name, "time_logs", "project");
+	}
+}
\ No newline at end of file
diff --git a/erpnext/projects/doctype/timesheet/timesheet.json b/erpnext/projects/doctype/timesheet/timesheet.json
index c29c11b..4c2edf4 100644
--- a/erpnext/projects/doctype/timesheet/timesheet.json
+++ b/erpnext/projects/doctype/timesheet/timesheet.json
@@ -1,1133 +1,352 @@
 {
- "allow_copy": 0, 
- "allow_events_in_timeline": 0, 
- "allow_guest_to_view": 0, 
- "allow_import": 1, 
- "allow_rename": 0, 
- "autoname": "naming_series:", 
- "beta": 0, 
- "creation": "2013-02-28 17:57:33", 
- "custom": 0, 
- "description": "", 
- "docstatus": 0, 
- "doctype": "DocType", 
- "document_type": "Document", 
- "editable_grid": 1, 
+ "actions": [],
+ "allow_import": 1,
+ "autoname": "naming_series:",
+ "creation": "2013-02-28 17:57:33",
+ "doctype": "DocType",
+ "document_type": "Document",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "title",
+  "naming_series",
+  "company",
+  "sales_invoice",
+  "column_break_3",
+  "salary_slip",
+  "status",
+  "project",
+  "employee_detail",
+  "employee",
+  "employee_name",
+  "department",
+  "column_break_9",
+  "user",
+  "start_date",
+  "end_date",
+  "section_break_5",
+  "time_logs",
+  "working_hours",
+  "total_hours",
+  "billing_details",
+  "total_billable_hours",
+  "total_billed_hours",
+  "total_costing_amount",
+  "column_break_10",
+  "total_billable_amount",
+  "total_billed_amount",
+  "per_billed",
+  "section_break_18",
+  "note",
+  "amended_from"
+ ],
  "fields": [
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 1, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "default": "{employee_name}", 
-   "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": 1, 
-   "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_on_submit": 1,
+   "default": "{employee_name}",
+   "fieldname": "title",
+   "fieldtype": "Data",
+   "hidden": 1,
+   "label": "Title",
+   "no_copy": 1,
+   "print_hide": 1
+  },
   {
-   "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": "Series", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "TS-.YYYY.-", 
-   "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": 1, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "naming_series",
+   "fieldtype": "Select",
+   "label": "Series",
+   "options": "TS-.YYYY.-",
+   "reqd": 1,
+   "set_only_once": 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": 1, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "company",
+   "fieldtype": "Link",
+   "label": "Company",
+   "options": "Company",
+   "remember_last_selected_value": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "depends_on": "", 
-   "description": "", 
-   "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": 0, 
-   "in_standard_filter": 0, 
-   "label": "Sales Invoice", 
-   "length": 0, 
-   "no_copy": 1, 
-   "options": "Sales Invoice", 
-   "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": "sales_invoice",
+   "fieldtype": "Link",
+   "label": "Sales Invoice",
+   "no_copy": 1,
+   "options": "Sales Invoice",
+   "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, 
-   "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, 
-   "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, 
-   "depends_on": "", 
-   "fieldname": "salary_slip", 
-   "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": "Salary Slip", 
-   "length": 0, 
-   "no_copy": 1, 
-   "options": "Salary Slip", 
-   "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": "salary_slip",
+   "fieldtype": "Link",
+   "label": "Salary Slip",
+   "no_copy": 1,
+   "options": "Salary Slip",
+   "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, 
-   "default": "Draft", 
-   "fieldname": "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": 1, 
-   "label": "Status", 
-   "length": 0, 
-   "no_copy": 1, 
-   "options": "Draft\nSubmitted\nBilled\nPayslip\nCompleted\nCancelled", 
-   "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
-  }, 
+   "default": "Draft",
+   "fieldname": "status",
+   "fieldtype": "Select",
+   "in_standard_filter": 1,
+   "label": "Status",
+   "no_copy": 1,
+   "options": "Draft\nSubmitted\nBilled\nPayslip\nCompleted\nCancelled",
+   "print_hide": 1,
+   "read_only": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "collapsible_depends_on": "", 
-   "columns": 0, 
-   "depends_on": "eval:!doc.work_order || doc.docstatus == 1", 
-   "fieldname": "employee_detail", 
-   "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": "Employee Detail", 
-   "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
-  }, 
+   "depends_on": "eval:!doc.work_order || doc.docstatus == 1",
+   "fieldname": "employee_detail",
+   "fieldtype": "Section Break",
+   "label": "Employee Detail"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "depends_on": "", 
-   "description": "", 
-   "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": 1, 
-   "label": "Employee", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Employee", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "employee",
+   "fieldtype": "Link",
+   "in_standard_filter": 1,
+   "label": "Employee",
+   "options": "Employee"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "depends_on": "employee", 
-   "fieldname": "employee_name", 
-   "fieldtype": "Data", 
-   "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": "Employee Name", 
-   "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": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "depends_on": "employee",
+   "fieldname": "employee_name",
+   "fieldtype": "Data",
+   "in_global_search": 1,
+   "label": "Employee Name",
+   "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_from": "employee.department", 
-   "fieldname": "department", 
-   "fieldtype": "Link", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Department", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Department", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 1, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "fetch_from": "employee.department",
+   "fieldname": "department",
+   "fieldtype": "Link",
+   "label": "Department",
+   "options": "Department",
+   "read_only": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "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
-  }, 
+   "fieldname": "column_break_9",
+   "fieldtype": "Column Break"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "user", 
-   "fieldtype": "Link", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 1, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "User", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "User", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 1, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "user",
+   "fieldtype": "Link",
+   "in_global_search": 1,
+   "label": "User",
+   "options": "User",
+   "read_only": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "start_date", 
-   "fieldtype": "Date", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Start 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
-  }, 
+   "fieldname": "start_date",
+   "fieldtype": "Date",
+   "in_list_view": 1,
+   "label": "Start 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, 
-   "fieldname": "end_date", 
-   "fieldtype": "Date", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "End Date", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 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": "end_date",
+   "fieldtype": "Date",
+   "label": "End 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, 
-   "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, 
-   "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": "time_logs", 
-   "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": "Time Sheets", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Timesheet Detail", 
-   "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
-  }, 
+   "fieldname": "time_logs",
+   "fieldtype": "Table",
+   "label": "Time Sheets",
+   "options": "Timesheet Detail",
+   "reqd": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "working_hours", 
-   "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": "working_hours",
+   "fieldtype": "Section Break"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 1, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "default": "0", 
-   "description": "", 
-   "fieldname": "total_hours", 
-   "fieldtype": "Float", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Total Working Hours", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 1, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "allow_on_submit": 1,
+   "default": "0",
+   "fieldname": "total_hours",
+   "fieldtype": "Float",
+   "in_list_view": 1,
+   "label": "Total Working Hours",
+   "read_only": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 1, 
-   "columns": 0, 
-   "fieldname": "billing_details", 
-   "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": "Billing Details", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 1, 
-   "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
-  }, 
+   "collapsible": 1,
+   "fieldname": "billing_details",
+   "fieldtype": "Section Break",
+   "label": "Billing Details",
+   "permlevel": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 1, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "total_billable_hours", 
-   "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 Billable Hours", 
-   "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
-  }, 
+   "allow_on_submit": 1,
+   "fieldname": "total_billable_hours",
+   "fieldtype": "Float",
+   "label": "Total Billable Hours",
+   "print_hide": 1,
+   "read_only": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 1, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "total_billed_hours", 
-   "fieldtype": "Float", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Total Billed Hours", 
-   "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
-  }, 
+   "allow_on_submit": 1,
+   "fieldname": "total_billed_hours",
+   "fieldtype": "Float",
+   "in_list_view": 1,
+   "label": "Total Billed Hours",
+   "print_hide": 1,
+   "read_only": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 1, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "total_costing_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 Costing Amount", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 1, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 1, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "allow_on_submit": 1,
+   "fieldname": "total_costing_amount",
+   "fieldtype": "Currency",
+   "label": "Total Costing Amount",
+   "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, 
-   "fieldname": "column_break_10", 
-   "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_10",
+   "fieldtype": "Column Break"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 1, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "default": "0", 
-   "depends_on": "", 
-   "description": "", 
-   "fieldname": "total_billable_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 Billable 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_on_submit": 1,
+   "default": "0",
+   "fieldname": "total_billable_amount",
+   "fieldtype": "Currency",
+   "label": "Total Billable Amount",
+   "read_only": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 1, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "total_billed_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 Billed Amount", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 1, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 1, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "allow_on_submit": 1,
+   "fieldname": "total_billed_amount",
+   "fieldtype": "Currency",
+   "label": "Total Billed Amount",
+   "print_hide": 1,
+   "read_only": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 1, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "per_billed", 
-   "fieldtype": "Percent", 
-   "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 Billed", 
-   "length": 0, 
-   "no_copy": 1, 
-   "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
-  }, 
+   "allow_on_submit": 1,
+   "fieldname": "per_billed",
+   "fieldtype": "Percent",
+   "label": "% Amount Billed",
+   "no_copy": 1,
+   "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, 
-   "fieldname": "section_break_18", 
-   "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_18",
+   "fieldtype": "Section Break"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "note", 
-   "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": "Note", 
-   "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": "note",
+   "fieldtype": "Text Editor",
+   "label": "Note"
+  },
   {
-   "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": 1, 
-   "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": "Timesheet", 
-   "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",
+   "ignore_user_permissions": 1,
+   "label": "Amended From",
+   "no_copy": 1,
+   "options": "Timesheet",
+   "print_hide": 1,
+   "read_only": 1
+  },
+  {
+   "fieldname": "project",
+   "fieldtype": "Link",
+   "label": "Project",
+   "options": "Project"
   }
- ], 
- "has_web_view": 0, 
- "hide_heading": 0, 
- "hide_toolbar": 0, 
- "icon": "fa fa-clock-o", 
- "idx": 1, 
- "image_view": 0, 
- "in_create": 0, 
- "is_submittable": 1, 
- "issingle": 0, 
- "istable": 0, 
- "max_attachments": 0, 
- "modified": "2019-03-05 21:54:02.654690", 
- "modified_by": "Administrator", 
- "module": "Projects", 
- "name": "Timesheet", 
- "owner": "Administrator", 
+ ],
+ "icon": "fa fa-clock-o",
+ "idx": 1,
+ "is_submittable": 1,
+ "links": [],
+ "modified": "2020-10-29 07:50:35.938231",
+ "modified_by": "Administrator",
+ "module": "Projects",
+ "name": "Timesheet",
+ "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": "Projects User", 
-   "set_user_permissions": 0, 
-   "share": 1, 
-   "submit": 1, 
+   "amend": 1,
+   "cancel": 1,
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "Projects User",
+   "share": 1,
+   "submit": 1,
    "write": 1
-  }, 
+  },
   {
-   "amend": 1, 
-   "cancel": 1, 
-   "create": 1, 
-   "delete": 1, 
-   "email": 1, 
-   "export": 1, 
-   "if_owner": 0, 
-   "import": 0, 
-   "permlevel": 0, 
-   "print": 1, 
-   "read": 1, 
-   "report": 1, 
-   "role": "HR User", 
-   "set_user_permissions": 0, 
-   "share": 1, 
-   "submit": 1, 
+   "amend": 1,
+   "cancel": 1,
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "export": 1,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "HR User",
+   "share": 1,
+   "submit": 1,
    "write": 1
-  }, 
+  },
   {
-   "amend": 1, 
-   "cancel": 1, 
-   "create": 1, 
-   "delete": 1, 
-   "email": 1, 
-   "export": 1, 
-   "if_owner": 0, 
-   "import": 0, 
-   "permlevel": 0, 
-   "print": 1, 
-   "read": 1, 
-   "report": 1, 
-   "role": "Manufacturing 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": "Manufacturing User",
+   "share": 1,
+   "submit": 1,
    "write": 1
-  }, 
+  },
   {
-   "amend": 0, 
-   "cancel": 0, 
-   "create": 1, 
-   "delete": 0, 
-   "email": 0, 
-   "export": 0, 
-   "if_owner": 0, 
-   "import": 0, 
-   "permlevel": 0, 
-   "print": 0, 
-   "read": 1, 
-   "report": 0, 
-   "role": "Employee", 
-   "set_user_permissions": 0, 
-   "share": 0, 
-   "submit": 0, 
+   "create": 1,
+   "read": 1,
+   "role": "Employee",
    "write": 1
-  }, 
+  },
   {
-   "amend": 1, 
-   "cancel": 1, 
-   "create": 1, 
-   "delete": 1, 
-   "email": 1, 
-   "export": 0, 
-   "if_owner": 0, 
-   "import": 0, 
-   "permlevel": 0, 
-   "print": 0, 
-   "read": 1, 
-   "report": 1, 
-   "role": "Accounts User", 
-   "set_user_permissions": 0, 
-   "share": 0, 
-   "submit": 1, 
+   "amend": 1,
+   "cancel": 1,
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "read": 1,
+   "report": 1,
+   "role": "Accounts User",
+   "submit": 1,
    "write": 1
-  }, 
+  },
   {
-   "amend": 0, 
-   "cancel": 0, 
-   "create": 0, 
-   "delete": 0, 
-   "email": 0, 
-   "export": 0, 
-   "if_owner": 0, 
-   "import": 0, 
-   "permlevel": 1, 
-   "print": 0, 
-   "read": 1, 
-   "report": 0, 
-   "role": "Accounts User", 
-   "set_user_permissions": 0, 
-   "share": 0, 
-   "submit": 0, 
+   "permlevel": 1,
+   "read": 1,
+   "role": "Accounts User",
    "write": 1
   }
- ], 
- "quick_entry": 0, 
- "read_only": 0, 
- "read_only_onload": 0, 
- "show_name_in_global_search": 0, 
- "sort_order": "ASC", 
- "title_field": "title", 
- "track_changes": 0, 
- "track_seen": 0, 
- "track_views": 0
+ ],
+ "sort_field": "modified",
+ "sort_order": "ASC",
+ "title_field": "title"
 }
\ No newline at end of file
diff --git a/erpnext/public/js/controllers/accounts.js b/erpnext/public/js/controllers/accounts.js
index 6e97d81..29f3595 100644
--- a/erpnext/public/js/controllers/accounts.js
+++ b/erpnext/public/js/controllers/accounts.js
@@ -146,18 +146,18 @@
 	if(!d.charge_type && d.account_head){
 		frappe.msgprint(__("Please select Charge Type first"));
 		frappe.model.set_value(cdt, cdn, "account_head", "");
-	} else if(d.account_head && d.charge_type!=="Actual") {
+	} else if (d.account_head) {
 		frappe.call({
 			type:"GET",
 			method: "erpnext.controllers.accounts_controller.get_tax_rate",
 			args: {"account_head":d.account_head},
 			callback: function(r) {
-				frappe.model.set_value(cdt, cdn, "rate", r.message.tax_rate || 0);
+				if (d.charge_type!=="Actual") {
+					frappe.model.set_value(cdt, cdn, "rate", r.message.tax_rate || 0);
+				}
 				frappe.model.set_value(cdt, cdn, "description", r.message.account_name);
 			}
 		})
-	} else if (d.charge_type == 'Actual' && d.account_head) {
-		frappe.model.set_value(cdt, cdn, "description", d.account_head.split(' - ')[0]);
 	}
 }
 
diff --git a/erpnext/public/js/controllers/buying.js b/erpnext/public/js/controllers/buying.js
index cb76c87..3f5652a 100644
--- a/erpnext/public/js/controllers/buying.js
+++ b/erpnext/public/js/controllers/buying.js
@@ -218,8 +218,7 @@
 		var is_negative_qty = false;
 		for(var i = 0; i<fieldnames.length; i++) {
 			if(item[fieldnames[i]] < 0){
-				frappe.msgprint(__("Row #{0}: {1} can not be negative for item {2}",
-					[item.idx,__(frappe.meta.get_label(cdt, fieldnames[i], cdn)), item.item_code]));
+				frappe.msgprint(__("Row #{0}: {1} can not be negative for item {2}", [item.idx,__(frappe.meta.get_label(cdt, fieldnames[i], cdn)), item.item_code]));
 				is_negative_qty = true;
 				break;
 			}
@@ -276,7 +275,7 @@
 		var me = this;
 		this.frm.add_custom_button(__("Product Bundle"), function() {
 			erpnext.buying.get_items_from_product_bundle(me.frm);
-		}, __("Get items from"));
+		}, __("Get Items From"));
 	},
 
 	shipping_address: function(){
diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js
index 1358a4b..7f08cd1 100644
--- a/erpnext/public/js/controllers/transaction.js
+++ b/erpnext/public/js/controllers/transaction.js
@@ -209,6 +209,17 @@
 			});
 		}
 
+		if (this.frm.fields_dict.taxes_and_charges) {
+			this.frm.set_query("taxes_and_charges", function() {
+				return {
+					filters: [
+						['company', '=', me.frm.doc.company],
+						['docstatus', '!=', 2]
+					]
+				};
+			});
+		}
+
 	},
 	onload: function() {
 		var me = this;
diff --git a/erpnext/public/js/hub/pages/Category.vue b/erpnext/public/js/hub/pages/Category.vue
index 057fe8b..16d0601 100644
--- a/erpnext/public/js/hub/pages/Category.vue
+++ b/erpnext/public/js/hub/pages/Category.vue
@@ -32,7 +32,7 @@
 			item_id_fieldname: 'name',
 
 			// Constants
-			empty_state_message: __(`No items in this category yet.`),
+			empty_state_message: __('No items in this category yet.'),
 
 			search_value: '',
 
diff --git a/erpnext/public/js/hub/pages/FeaturedItems.vue b/erpnext/public/js/hub/pages/FeaturedItems.vue
index ab9990a..63ae7e9 100644
--- a/erpnext/public/js/hub/pages/FeaturedItems.vue
+++ b/erpnext/public/js/hub/pages/FeaturedItems.vue
@@ -33,10 +33,8 @@
 
 			// Constants
 			page_title: __('Your Featured Items'),
-            empty_state_message: __(`No featured items yet. Got to your 
-                                <a href="#marketplace/published-items">
-                                Published Items</a> 
-                                and feature upto 8 items that you want to highlight to your customers.`)
+			empty_state_message: __('No featured items yet. Got to your {0} and feature up to eight items that you want to highlight to your customers.',
+				[`<a href="#marketplace/published-items">${__("Published Items")}</a>`])
 		};
 	},
 	created() {
@@ -71,9 +69,9 @@
 
 			const item_name = this.items.filter(item => item.hub_item_name === hub_item_name);
 
-			alert = frappe.show_alert(__(`<span>${item_name} removed.
-				<a href="#" data-action="undo-remove"><b>Undo</b></a></span>`),
-				grace_period/1000,
+			alert_message = __('{0} removed. {1}', [item_name, 
+				`<a href="#" data-action="undo-remove"><b>${__('Undo')}</b></a>`]);
+			alert = frappe.show_alert(alert_message, grace_period / 1000,
 				{
 					'undo-remove': undo_remove.bind(this)
 				}
diff --git a/erpnext/public/js/hub/pages/Item.vue b/erpnext/public/js/hub/pages/Item.vue
index 51ade42..93002a7 100644
--- a/erpnext/public/js/hub/pages/Item.vue
+++ b/erpnext/public/js/hub/pages/Item.vue
@@ -113,12 +113,12 @@
 
 			let stats = __('No views yet');
 			if (this.item.view_count) {
-				const views_message = __(`${this.item.view_count} Views`);
+				const views_message = __('{0} Views', [this.item.view_count]);
 
 				const rating_html = get_rating_html(this.item.average_rating);
 				const rating_count =
 					this.item.no_of_ratings > 0
-						? `${this.item.no_of_ratings} reviews`
+						? __('{0} reviews', [this.item.no_of_ratings])
 						: __('No reviews yet');
 
 				stats = [views_message, rating_html, rating_count];
@@ -310,7 +310,7 @@
 					return this.get_item_details();
 				})
 				.then(() => {
-					frappe.show_alert(__(`${this.item.item_name} Updated`));
+					frappe.show_alert(__('{0} Updated', [this.item.item_name]));
 				});
 		},
 
@@ -337,7 +337,7 @@
 		},
 
 		unpublish_item() {
-			frappe.confirm(__(`Unpublish {0}?`, [this.item.item_name]), () => {
+			frappe.confirm(__('Unpublish {0}?', [this.item.item_name]), () => {
 				frappe
 					.call('erpnext.hub_node.api.unpublish_item', {
 						item_code: this.item.item_code,
diff --git a/erpnext/public/js/hub/pages/NotFound.vue b/erpnext/public/js/hub/pages/NotFound.vue
index 246d31b..8901b97 100644
--- a/erpnext/public/js/hub/pages/NotFound.vue
+++ b/erpnext/public/js/hub/pages/NotFound.vue
@@ -27,7 +27,7 @@
 			},
 
 			// Constants
-			empty_state_message: __(`Sorry! I could not find what you were looking for.`)
+			empty_state_message: __('Sorry! We could not find what you were looking for.')
 		};
 	},
 }
diff --git a/erpnext/public/js/hub/pages/Publish.vue b/erpnext/public/js/hub/pages/Publish.vue
index 735f2b9..96fa0aa 100644
--- a/erpnext/public/js/hub/pages/Publish.vue
+++ b/erpnext/public/js/hub/pages/Publish.vue
@@ -75,14 +75,11 @@
 			// TODO: multiline translations don't work
 			page_title: __('Publish Items'),
 			search_placeholder: __('Search Items ...'),
-			empty_state_message: __(`No Items selected yet. Browse and click on items below to publish.`),
-			valid_items_instruction: __(`Only items with an image and description can be published. Please update them if an item in your inventory does not appear.`),
+			empty_state_message: __('No Items selected yet. Browse and click on items below to publish.'),
+			valid_items_instruction: __('Only items with an image and description can be published. Please update them if an item in your inventory does not appear.'),
 			last_sync_message: (hub.settings.last_sync_datetime)
-				? __(`Last sync was
-				<a href="#marketplace/profile">
-					${comment_when(hub.settings.last_sync_datetime)}</a>.
-				<a href="#marketplace/published-items">
-					See your Published Items</a>.`)
+				? __('Last sync was {0}.', [`<a href="#marketplace/profile">${comment_when(hub.settings.last_sync_datetime)}</a>`]) + 
+				  ` <a href="#marketplace/published-items">${__('See your Published Items.')}</a>`
 				: ''
 		};
 	},
@@ -147,11 +144,9 @@
 		},
 
 		add_last_sync_message() {
-			this.last_sync_message = __(`Last sync was
-				<a href="#marketplace/profile">
-					${comment_when(hub.settings.last_sync_datetime)}</a>.
-				<a href="#marketplace/published-items">
-					See your Published Items</a>.`);
+			this.last_sync_message = __('Last sync was {0}.',
+				[`<a href="#marketplace/profile">${comment_when(hub.settings.last_sync_datetime)}</a>`]
+			) + `<a href="#marketplace/published-items">${__('See your Published Items')}</a>.`;
 		},
 
 		clear_last_sync_message() {
diff --git a/erpnext/public/js/hub/pages/SavedItems.vue b/erpnext/public/js/hub/pages/SavedItems.vue
index c29675a..7007ddc 100644
--- a/erpnext/public/js/hub/pages/SavedItems.vue
+++ b/erpnext/public/js/hub/pages/SavedItems.vue
@@ -29,7 +29,7 @@
 
 			// Constants
 			page_title: __('Saved Items'),
-			empty_state_message: __(`You haven't saved any items yet.`)
+			empty_state_message: __('You have not saved any items yet.')
 		};
 	},
 	created() {
@@ -64,8 +64,13 @@
 
 			const item_name = this.items.filter(item => item.hub_item_name === hub_item_name);
 
-			alert = frappe.show_alert(__(`<span>${item_name} removed.
-				<a href="#" data-action="undo-remove"><b>Undo</b></a></span>`),
+			alert = frappe.show_alert(`
+				<span>
+					${__('{0} removed.', [item_name], 'A specific Item has been removed.')}
+					<a href="#" data-action="undo-remove">
+						<b>${__('Undo', None, 'Undo removal of item.')}</b>
+					</a>
+				</span>`,
 				grace_period/1000,
 				{
 					'undo-remove': undo_remove.bind(this)
diff --git a/erpnext/public/js/hub/pages/Search.vue b/erpnext/public/js/hub/pages/Search.vue
index 1032842..c10841e 100644
--- a/erpnext/public/js/hub/pages/Search.vue
+++ b/erpnext/public/js/hub/pages/Search.vue
@@ -42,7 +42,10 @@
 	computed: {
 		page_title() {
 			return this.items.length
-				? __(`Results for "${this.search_value}" ${this.category !== 'All'? `in category ${this.category}` : ''}`)
+				? __('Results for "{0}" {1}', [
+					this.search_value,
+					this.category !== 'All' ? __('in category {0}', [this.category]) : ''
+				  ])
 				: __('No Items found.');
 		}
 	},
diff --git a/erpnext/public/js/hub/pages/Seller.vue b/erpnext/public/js/hub/pages/Seller.vue
index e339eaa..c0903c6 100644
--- a/erpnext/public/js/hub/pages/Seller.vue
+++ b/erpnext/public/js/hub/pages/Seller.vue
@@ -136,7 +136,7 @@
 				this.init = false;
 				this.profile = data.profile;
 				this.items = data.items;
-				this.item_container_heading = data.is_featured_item? "Features Items":"Popular Items";
+				this.item_container_heading = data.is_featured_item ? __('Featured Items') : __('Popular Items');
 				this.hub_seller = this.items[0].hub_seller;
 				this.recent_seller_reviews = data.recent_seller_reviews;
 				this.seller_product_view_stats = data.seller_product_view_stats;
@@ -147,7 +147,7 @@
 
 				this.country = __(profile.country);
 				this.site_name = __(profile.site_name);
-				this.joined_when = __(`Joined ${comment_when(profile.creation)}`);
+				this.joined_when = __('Joined {0}', [comment_when(profile.creation)]);
 
 				this.image = profile.logo;
 				this.sections = [
diff --git a/erpnext/public/js/salary_slip_deductions_report_filters.js b/erpnext/public/js/salary_slip_deductions_report_filters.js
index 2b30e65..1ca3660 100644
--- a/erpnext/public/js/salary_slip_deductions_report_filters.js
+++ b/erpnext/public/js/salary_slip_deductions_report_filters.js
@@ -45,7 +45,7 @@
 		},
 		{
 			fieldname: "branch",
-			label: __("Barnch"),
+			label: __("Branch"),
 			fieldtype: "Link",
 			options: "Branch",
 		}
@@ -63,4 +63,4 @@
 			}
 		});
 	}
-}
\ No newline at end of file
+}
diff --git a/erpnext/public/js/setup_wizard.js b/erpnext/public/js/setup_wizard.js
index 5d21190..092f839 100644
--- a/erpnext/public/js/setup_wizard.js
+++ b/erpnext/public/js/setup_wizard.js
@@ -161,7 +161,10 @@
 						if(r.message){
 							exist = r.message;
 							me.get_field("bank_account").set_value("");
-							frappe.msgprint(__(`Account ${me.values.bank_account} already exists, enter a different name for your bank account`));
+							let message = __('Account {0} already exists. Please enter a different name for your bank account.',
+								[me.values.bank_account]
+							);
+							frappe.msgprint(message);
 						}
 					}
 				});
diff --git a/erpnext/regional/doctype/datev_settings/datev_settings.js b/erpnext/regional/doctype/datev_settings/datev_settings.js
index 69747b0..f047059 100644
--- a/erpnext/regional/doctype/datev_settings/datev_settings.js
+++ b/erpnext/regional/doctype/datev_settings/datev_settings.js
@@ -2,7 +2,7 @@
 // For license information, please see license.txt
 
 frappe.ui.form.on('DATEV Settings', {
-	// refresh: function(frm) {
-
-	// }
+	refresh: function(frm) {
+		frm.add_custom_button('Show Report', () => frappe.set_route('query-report', 'DATEV'), "fa fa-table");
+	}
 });
diff --git a/erpnext/regional/doctype/datev_settings/datev_settings.json b/erpnext/regional/doctype/datev_settings/datev_settings.json
index 39486df..713e8e3 100644
--- a/erpnext/regional/doctype/datev_settings/datev_settings.json
+++ b/erpnext/regional/doctype/datev_settings/datev_settings.json
@@ -1,4 +1,5 @@
 {
+ "actions": [],
  "autoname": "field:client",
  "creation": "2019-08-13 23:56:34.259906",
  "doctype": "DocType",
@@ -6,6 +7,7 @@
  "engine": "InnoDB",
  "field_order": [
   "client",
+  "account_number_length",
   "column_break_2",
   "client_number",
   "section_break_4",
@@ -28,8 +30,8 @@
    "fieldtype": "Data",
    "in_list_view": 1,
    "label": "Client ID",
-   "reqd": 1,
-   "length": 5
+   "length": 5,
+   "reqd": 1
   },
   {
    "fieldname": "consultant",
@@ -43,8 +45,8 @@
    "fieldtype": "Data",
    "in_list_view": 1,
    "label": "Consultant ID",
-   "reqd": 1,
-   "length": 7
+   "length": 7,
+   "reqd": 1
   },
   {
    "fieldname": "column_break_2",
@@ -57,9 +59,17 @@
   {
    "fieldname": "column_break_6",
    "fieldtype": "Column Break"
+  },
+  {
+   "default": "4",
+   "fieldname": "account_number_length",
+   "fieldtype": "Int",
+   "label": "Account Number Length",
+   "reqd": 1
   }
  ],
- "modified": "2019-08-14 00:03:26.616460",
+ "links": [],
+ "modified": "2020-11-05 17:52:11.674329",
  "modified_by": "Administrator",
  "module": "Regional",
  "name": "DATEV Settings",
@@ -104,4 +114,4 @@
  "sort_field": "modified",
  "sort_order": "DESC",
  "track_changes": 1
-}
+}
\ No newline at end of file
diff --git a/erpnext/regional/doctype/uae_vat_account/__init__.py b/erpnext/regional/doctype/uae_vat_account/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/regional/doctype/uae_vat_account/__init__.py
diff --git a/erpnext/regional/doctype/uae_vat_account/uae_vat_account.json b/erpnext/regional/doctype/uae_vat_account/uae_vat_account.json
new file mode 100644
index 0000000..73a8169
--- /dev/null
+++ b/erpnext/regional/doctype/uae_vat_account/uae_vat_account.json
@@ -0,0 +1,35 @@
+{
+ "actions": [],
+ "autoname": "account",
+ "creation": "2020-09-28 11:30:45.472053",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "account"
+ ],
+ "fields": [
+  {
+   "allow_in_quick_entry": 1,
+   "fieldname": "account",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "in_preview": 1,
+   "label": "Account",
+   "options": "Account"
+  }
+ ],
+ "index_web_pages_for_search": 1,
+ "istable": 1,
+ "links": [],
+ "modified": "2020-09-28 12:02:56.444007",
+ "modified_by": "Administrator",
+ "module": "Regional",
+ "name": "UAE VAT Account",
+ "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/regional/doctype/uae_vat_account/uae_vat_account.py b/erpnext/regional/doctype/uae_vat_account/uae_vat_account.py
new file mode 100644
index 0000000..80d6b3a
--- /dev/null
+++ b/erpnext/regional/doctype/uae_vat_account/uae_vat_account.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+# import frappe
+from frappe.model.document import Document
+
+class UAEVATAccount(Document):
+	pass
diff --git a/erpnext/regional/doctype/uae_vat_settings/__init__.py b/erpnext/regional/doctype/uae_vat_settings/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/regional/doctype/uae_vat_settings/__init__.py
diff --git a/erpnext/regional/doctype/uae_vat_settings/test_uae_vat_settings.py b/erpnext/regional/doctype/uae_vat_settings/test_uae_vat_settings.py
new file mode 100644
index 0000000..b88439f
--- /dev/null
+++ b/erpnext/regional/doctype/uae_vat_settings/test_uae_vat_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 TestUAEVATSettings(unittest.TestCase):
+	pass
diff --git a/erpnext/regional/doctype/uae_vat_settings/uae_vat_settings.js b/erpnext/regional/doctype/uae_vat_settings/uae_vat_settings.js
new file mode 100644
index 0000000..07a9301
--- /dev/null
+++ b/erpnext/regional/doctype/uae_vat_settings/uae_vat_settings.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('UAE VAT Settings', {
+	// refresh: function(frm) {
+
+	// }
+});
diff --git a/erpnext/regional/doctype/uae_vat_settings/uae_vat_settings.json b/erpnext/regional/doctype/uae_vat_settings/uae_vat_settings.json
new file mode 100644
index 0000000..ce2c1d4
--- /dev/null
+++ b/erpnext/regional/doctype/uae_vat_settings/uae_vat_settings.json
@@ -0,0 +1,55 @@
+{
+ "actions": [],
+ "autoname": "field:company",
+ "creation": "2020-09-25 12:48:51.463265",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "company",
+  "uae_vat_accounts"
+ ],
+ "fields": [
+  {
+   "fieldname": "company",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "label": "Company",
+   "options": "Company",
+   "reqd": 1,
+   "unique": 1
+  },
+  {
+   "fieldname": "uae_vat_accounts",
+   "fieldtype": "Table",
+   "label": "UAE VAT Accounts",
+   "options": "UAE VAT Account",
+   "reqd": 1
+  }
+ ],
+ "index_web_pages_for_search": 1,
+ "links": [],
+ "modified": "2020-09-30 20:08:18.764798",
+ "modified_by": "Administrator",
+ "module": "Regional",
+ "name": "UAE VAT Settings",
+ "owner": "Administrator",
+ "permissions": [
+  {
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "export": 1,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "System Manager",
+   "share": 1,
+   "write": 1
+  }
+ ],
+ "quick_entry": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/regional/doctype/uae_vat_settings/uae_vat_settings.py b/erpnext/regional/doctype/uae_vat_settings/uae_vat_settings.py
new file mode 100644
index 0000000..20dc604
--- /dev/null
+++ b/erpnext/regional/doctype/uae_vat_settings/uae_vat_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 UAEVATSettings(Document):
+	pass
diff --git a/erpnext/regional/germany/accounts_controller.py b/erpnext/regional/germany/accounts_controller.py
index 193c8e1..5b2b31f 100644
--- a/erpnext/regional/germany/accounts_controller.py
+++ b/erpnext/regional/germany/accounts_controller.py
@@ -15,8 +15,7 @@
 		},
 		{
 			"field_name": "taxes",
-			"regulation": "§ 14 Abs. 4 Nr. 8 UStG",
-			"condition": "not exempt_from_sales_tax"
+			"regulation": "§ 14 Abs. 4 Nr. 8 UStG"
 		},
 		{
 			"field_name": "customer_address",
diff --git a/erpnext/regional/germany/utils/datev/datev_csv.py b/erpnext/regional/germany/utils/datev/datev_csv.py
index aae734f..f138a80 100644
--- a/erpnext/regional/germany/utils/datev/datev_csv.py
+++ b/erpnext/regional/germany/utils/datev/datev_csv.py
@@ -104,9 +104,9 @@
 		# L = Tax client number (Mandantennummer)
 		datev_settings.get('client_number', '00000'),
 		# M = Start of the fiscal year (Wirtschaftsjahresbeginn)
-		frappe.utils.formatdate(frappe.defaults.get_user_default('year_start_date'), 'yyyyMMdd'),
+		frappe.utils.formatdate(filters.get('fiscal_year_start'), 'yyyyMMdd'),
 		# N = Length of account numbers (Sachkontenlänge)
-		datev_settings.get('account_number_length', '4'),
+		str(filters.get('account_number_length', 4)),
 		# O = Transaction batch start date (YYYYMMDD)
 		frappe.utils.formatdate(filters.get('from_date'), 'yyyyMMdd') if csv_class.DATA_CATEGORY == DataCategory.TRANSACTIONS else '',
 		# P = Transaction batch end date (YYYYMMDD)
@@ -155,20 +155,22 @@
 	return header
 
 
-def download_csv_files_as_zip(csv_data_list):
+def zip_and_download(zip_filename, csv_files):
 	"""
 	Put CSV files in a zip archive and send that to the client.
 
 	Params:
-	csv_data_list -- list of dicts [{'file_name': 'EXTF_Buchunsstapel.zip', 'csv_data': get_datev_csv()}]
+	zip_filename	Name of the zip file
+	csv_files		list of dicts [{'file_name': 'my_file.csv', 'csv_data': 'comma,separated,values'}]
 	"""
 	zip_buffer = BytesIO()
 
-	datev_zip = zipfile.ZipFile(zip_buffer, mode='w', compression=zipfile.ZIP_DEFLATED)
-	for csv_file in csv_data_list:
-		datev_zip.writestr(csv_file.get('file_name'), csv_file.get('csv_data'))
-	datev_zip.close()
+	zip_file = zipfile.ZipFile(zip_buffer, mode='w', compression=zipfile.ZIP_DEFLATED)
+	for csv_file in csv_files:
+		zip_file.writestr(csv_file.get('file_name'), csv_file.get('csv_data'))
+
+	zip_file.close()
 
 	frappe.response['filecontent'] = zip_buffer.getvalue()
-	frappe.response['filename'] = 'DATEV.zip'
+	frappe.response['filename'] = zip_filename
 	frappe.response['type'] = 'binary'
diff --git a/erpnext/regional/india/taxes.js b/erpnext/regional/india/taxes.js
index 3b6a28f..3c15647 100644
--- a/erpnext/regional/india/taxes.js
+++ b/erpnext/regional/india/taxes.js
@@ -31,12 +31,12 @@
 				args: {
 					party_details: JSON.stringify(party_details),
 					doctype: frm.doc.doctype,
-					company: frm.doc.company,
-					return_taxes: 1
+					company: frm.doc.company
 				},
 				callback: function(r) {
 					if(r.message) {
 						frm.set_value('taxes_and_charges', r.message.taxes_and_charges);
+						frm.set_value('place_of_supply', r.message.place_of_supply);
 					} else if (frm.doc.is_internal_supplier || frm.doc.is_internal_customer) {
 						frm.set_value('taxes_and_charges', '');
 						frm.set_value('taxes', []);
diff --git a/erpnext/regional/india/utils.py b/erpnext/regional/india/utils.py
index dd87f0f..62487ba 100644
--- a/erpnext/regional/india/utils.py
+++ b/erpnext/regional/india/utils.py
@@ -51,6 +51,13 @@
 			frappe.throw(_("Invalid GSTIN! First 2 digits of GSTIN should match with State number {0}.")
 				.format(doc.gst_state_number))
 
+def validate_tax_category(doc, method):
+	if doc.get('gst_state') and frappe.db.get_value('Tax category', {'gst_state': doc.gst_state, 'is_inter_state': doc.is_inter_state}):
+		if doc.is_inter_state:
+			frappe.throw(_("Inter State tax category for GST State {0} already exists").format(doc.gst_state))
+		else:
+			frappe.throw(_("Intra State tax category for GST State {0} already exists").format(doc.gst_state))
+
 def update_gst_category(doc, method):
 	for link in doc.links:
 		if link.link_doctype in ['Customer', 'Supplier']:
@@ -85,8 +92,7 @@
 		total += digit
 		factor = 2 if factor == 1 else 1
 	if gstin[-1] != code_point_chars[((mod - (total % mod)) % mod)]:
-		frappe.throw(_("""Invalid {0}! The check digit validation has failed.
-			Please ensure you've typed the {0} correctly.""".format(label)))
+		frappe.throw(_("""Invalid {0}! The check digit validation has failed. Please ensure you've typed the {0} correctly.""").format(label))
 
 def get_itemised_tax_breakup_header(item_doctype, tax_accounts):
 	if frappe.get_meta(item_doctype).has_field('gst_hsn_code'):
@@ -150,7 +156,7 @@
 			return cstr(address.gst_state_number) + "-" + cstr(address.gst_state)
 
 @frappe.whitelist()
-def get_regional_address_details(party_details, doctype, company, return_taxes=None):
+def get_regional_address_details(party_details, doctype, company):
 	if isinstance(party_details, string_types):
 		party_details = json.loads(party_details)
 		party_details = frappe._dict(party_details)
@@ -160,7 +166,7 @@
 	if is_internal_transfer(party_details, doctype):
 		party_details.taxes_and_charges = ''
 		party_details.taxes = ''
-		return
+		return party_details
 
 	if doctype in ("Sales Invoice", "Delivery Note", "Sales Order"):
 		master_doctype = "Sales Taxes and Charges Template"
@@ -168,26 +174,26 @@
 		get_tax_template_for_sez(party_details, master_doctype, company, 'Customer')
 		get_tax_template_based_on_category(master_doctype, company, party_details)
 
-		if party_details.get('taxes_and_charges') and return_taxes:
+		if party_details.get('taxes_and_charges'):
 			return party_details
 
 		if not party_details.company_gstin:
-			return
+			return party_details
 
 	elif doctype in ("Purchase Invoice", "Purchase Order", "Purchase Receipt"):
 		master_doctype = "Purchase Taxes and Charges Template"
 		get_tax_template_for_sez(party_details, master_doctype, company, 'Supplier')
 		get_tax_template_based_on_category(master_doctype, company, party_details)
 
-		if party_details.get('taxes_and_charges') and return_taxes:
+		if party_details.get('taxes_and_charges'):
 			return party_details
 
 		if not party_details.supplier_gstin:
-			return
+			return party_details
 
-	if not party_details.place_of_supply: return
+	if not party_details.place_of_supply: return party_details
 
-	if not party_details.company_gstin: return
+	if not party_details.company_gstin: return party_details
 
 	if ((doctype in ("Sales Invoice", "Delivery Note", "Sales Order") and party_details.company_gstin
 		and party_details.company_gstin[:2] != party_details.place_of_supply[:2]) or (doctype in ("Purchase Invoice",
@@ -197,12 +203,11 @@
 		default_tax = get_tax_template(master_doctype, company, 0, party_details.company_gstin[:2])
 
 	if not default_tax:
-		return
+		return party_details
 	party_details["taxes_and_charges"] = default_tax
 	party_details.taxes = get_taxes_and_charges(master_doctype, default_tax)
 
-	if return_taxes:
-		return party_details
+	return party_details
 
 def is_internal_transfer(party_details, doctype):
 	if doctype in ("Sales Invoice", "Delivery Note", "Sales Order"):
@@ -236,7 +241,7 @@
 		if tax_category.gst_state == number_state_mapping[state_code] or \
 	 		(not default_tax and not tax_category.gst_state):
 			default_tax = frappe.db.get_value(master_doctype,
-				{'disabled': 0, 'tax_category': tax_category.name}, 'name')
+				{'company': company, 'disabled': 0, 'tax_category': tax_category.name}, 'name')
 	return default_tax
 
 def get_tax_template_for_sez(party_details, master_doctype, company, party_type):
@@ -517,6 +522,9 @@
 		data.actualToStateCode = data.toStateCode
 		shipping_address = billing_address
 
+	if doc.gst_category == 'SEZ':
+		data.toStateCode = 99
+
 	return data
 
 def get_item_list(data, doc):
@@ -752,4 +760,4 @@
 					}, account_currency, item=tax)
 				)
 
-	return gl_entries
\ No newline at end of file
+	return gl_entries
diff --git a/erpnext/regional/report/datev/datev.js b/erpnext/regional/report/datev/datev.js
index 55f12cf..4124e3d 100644
--- a/erpnext/regional/report/datev/datev.js
+++ b/erpnext/regional/report/datev/datev.js
@@ -11,14 +11,14 @@
 		{
 			"fieldname": "from_date",
 			"label": __("From Date"),
-			"default": frappe.datetime.month_start(),
+			"default": moment().subtract(1, 'month').startOf('month').format(),
 			"fieldtype": "Date",
 			"reqd": 1
 		},
 		{
 			"fieldname": "to_date",
 			"label": __("To Date"),
-			"default": frappe.datetime.now_date(),
+			"default": moment().subtract(1, 'month').endOf('month').format(),
 			"fieldtype": "Date",
 			"reqd": 1
 		},
@@ -30,9 +30,23 @@
 		}
 	],
 	onload: function(query_report) {
+		let company = frappe.query_report.get_filter_value('company');
+		frappe.db.exists('DATEV Settings', company).then((settings_exist) => {
+			if (!settings_exist) {
+				frappe.confirm(__('DATEV Settings for your Company are missing. Would you like to create them now?'),
+					() => frappe.new_doc('DATEV Settings', {'company': company})
+				);
+			}
+		});
+
 		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}`);
 		});
+
+		query_report.page.add_menu_item(__("Change DATEV Settings"), () => {
+			let company = frappe.query_report.get_filter_value('company'); // read company from filters again – it might have changed by now.
+			frappe.set_route('Form', 'DATEV Settings', company);
+		});
 	}
 };
diff --git a/erpnext/regional/report/datev/datev.py b/erpnext/regional/report/datev/datev.py
index dd818e6..1e39c57 100644
--- a/erpnext/regional/report/datev/datev.py
+++ b/erpnext/regional/report/datev/datev.py
@@ -11,9 +11,11 @@
 
 import json
 import frappe
-from frappe import _
 from six import string_types
-from erpnext.regional.germany.utils.datev.datev_csv import download_csv_files_as_zip, get_datev_csv
+
+from frappe import _
+from erpnext.accounts.utils import get_fiscal_year
+from erpnext.regional.germany.utils.datev.datev_csv import zip_and_download, get_datev_csv
 from erpnext.regional.germany.utils.datev.datev_constants import Transactions, DebtorsCreditors, AccountNames
 
 COLUMNS = [
@@ -92,25 +94,44 @@
 
 def execute(filters=None):
 	"""Entry point for frappe."""
-	validate(filters)
-	return COLUMNS, get_transactions(filters, as_dict=0)
+	data = []
+	if filters and validate(filters):
+		data = get_transactions(filters, as_dict=0)
+
+	return COLUMNS, data
 
 
 def validate(filters):
 	"""Make sure all mandatory filters and settings are present."""
-	if not filters.get('company'):
+	company = filters.get('company')
+	if not company:
 		frappe.throw(_('<b>Company</b> is a mandatory filter.'))
 
-	if not filters.get('from_date'):
+	from_date = filters.get('from_date')
+	if not from_date:
 		frappe.throw(_('<b>From Date</b> is a mandatory filter.'))
 
-	if not filters.get('to_date'):
+	to_date = filters.get('to_date')
+	if not to_date:
 		frappe.throw(_('<b>To Date</b> is a mandatory filter.'))
 
-	try:
-		frappe.get_doc('DATEV Settings', filters.get('company'))
-	except frappe.DoesNotExistError:
-		frappe.throw(_('Please create <b>DATEV Settings</b> for Company <b>{}</b>.').format(filters.get('company')))
+	validate_fiscal_year(from_date, to_date, company)
+
+	if not frappe.db.exists('DATEV Settings', filters.get('company')):
+		frappe.log_error(_('Please create {} for Company {}.').format(
+			'<a href="desk#List/DATEV%20Settings/List">{}</a>'.format(_('DATEV Settings')),
+			frappe.bold(filters.get('company'))
+		))
+		return False
+
+	return True
+
+
+def validate_fiscal_year(from_date, to_date, company):
+	from_fiscal_year = get_fiscal_year(date=from_date, company=company)
+	to_fiscal_year = get_fiscal_year(date=to_date, company=company)
+	if from_fiscal_year != to_fiscal_year:
+		frappe.throw(_('Dates {} and {} are not in the same fiscal year.').format(from_date, to_date))
 
 
 def get_transactions(filters, as_dict=1):
@@ -317,17 +338,24 @@
 		filters = json.loads(filters)
 
 	validate(filters)
+	company = filters.get('company')
+
+	fiscal_year = get_fiscal_year(date=filters.get('from_date'), company=company)
+	filters['fiscal_year_start'] = fiscal_year[1]
 
 	# set chart of accounts used
-	coa = frappe.get_value('Company', filters.get('company'), 'chart_of_accounts')
+	coa = frappe.get_value('Company', company, 'chart_of_accounts')
 	filters['skr'] = '04' if 'SKR04' in coa else ('03' if 'SKR03' in coa else '')
 
+	filters['account_number_length'] = frappe.get_value('DATEV Settings', company, 'account_number_length')
+
 	transactions = get_transactions(filters)
 	account_names = get_account_names(filters)
 	customers = get_customers(filters)
 	suppliers = get_suppliers(filters)
 
-	download_csv_files_as_zip([
+	zip_name = '{} DATEV.zip'.format(frappe.utils.datetime.date.today())
+	zip_and_download(zip_name, [
 		{
 			'file_name': 'EXTF_Buchungsstapel.csv',
 			'csv_data': get_datev_csv(transactions, filters, csv_class=Transactions)
diff --git a/erpnext/regional/report/uae_vat_201/__init__.py b/erpnext/regional/report/uae_vat_201/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/regional/report/uae_vat_201/__init__.py
diff --git a/erpnext/regional/report/uae_vat_201/test_uae_vat_201.py b/erpnext/regional/report/uae_vat_201/test_uae_vat_201.py
new file mode 100644
index 0000000..daa6976
--- /dev/null
+++ b/erpnext/regional/report/uae_vat_201/test_uae_vat_201.py
@@ -0,0 +1,239 @@
+# coding=utf-8
+from __future__ import unicode_literals
+
+import erpnext
+import frappe
+from unittest import TestCase
+from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
+from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import make_purchase_invoice
+from erpnext.stock.doctype.warehouse.test_warehouse import get_warehouse_account
+from erpnext.regional.report.uae_vat_201.uae_vat_201 import (
+	get_total_emiratewise,
+	get_tourist_tax_return_total,
+	get_tourist_tax_return_tax,
+	get_zero_rated_total,
+	get_exempt_total,
+	get_standard_rated_expenses_total,
+	get_standard_rated_expenses_tax,
+)
+
+test_dependencies = ["Territory", "Customer Group", "Supplier Group", "Item"]
+
+class TestUaeVat201(TestCase):
+	def setUp(self):
+		frappe.set_user("Administrator")
+
+		frappe.db.sql("delete from `tabSales Invoice` where company='_Test Company UAE VAT'")
+		frappe.db.sql("delete from `tabPurchase Invoice` where company='_Test Company UAE VAT'")
+
+		make_company("_Test Company UAE VAT", "_TCUV")
+		set_vat_accounts()
+
+		make_customer()
+
+		make_supplier()
+
+		create_warehouse("_Test UAE VAT Supplier Warehouse", company="_Test Company UAE VAT")
+
+		make_item("_Test UAE VAT Item", properties = {"is_zero_rated": 0, "is_exempt": 0})
+		make_item("_Test UAE VAT Zero Rated Item", properties = {"is_zero_rated": 1, "is_exempt": 0})
+		make_item("_Test UAE VAT Exempt Item", properties = {"is_zero_rated": 0, "is_exempt": 1})
+
+		make_sales_invoices()
+
+		create_purchase_invoices()
+
+	def test_uae_vat_201_report(self):
+		filters = {"company": "_Test Company UAE VAT"}
+		total_emiratewise = get_total_emiratewise(filters)
+		amounts_by_emirate = {}
+		for data in total_emiratewise:
+			emirate, amount, vat = data
+			amounts_by_emirate[emirate] = {
+				"raw_amount": amount,
+				"raw_vat_amount": vat,
+			}
+		self.assertEqual(amounts_by_emirate["Sharjah"]["raw_amount"],100)
+		self.assertEqual(amounts_by_emirate["Sharjah"]["raw_vat_amount"],5)
+		self.assertEqual(amounts_by_emirate["Dubai"]["raw_amount"],200)
+		self.assertEqual(amounts_by_emirate["Dubai"]["raw_vat_amount"],10)
+		self.assertEqual(get_tourist_tax_return_total(filters),100)
+		self.assertEqual(get_tourist_tax_return_tax(filters),2)
+		self.assertEqual(get_zero_rated_total(filters),100)
+		self.assertEqual(get_exempt_total(filters),100)
+		self.assertEqual(get_standard_rated_expenses_total(filters),250)
+		self.assertEqual(get_standard_rated_expenses_tax(filters),1)
+
+def make_company(company_name, abbr):
+	if not frappe.db.exists("Company", company_name):
+		company = frappe.get_doc({
+			"doctype": "Company",
+			"company_name": company_name,
+			"abbr": abbr,
+			"default_currency": "AED",
+			"country": "United Arab Emirates",
+			"create_chart_of_accounts_based_on": "Standard Template",
+		})
+		company.insert()
+	else:
+		company = frappe.get_doc("Company", company_name)
+
+	company.create_default_warehouses()
+
+	if not frappe.db.get_value("Cost Center", {"is_group": 0, "company": company.name}):
+		company.create_default_cost_center()
+
+	company.save()
+	return company
+
+def set_vat_accounts():
+	if not frappe.db.exists("UAE VAT Settings", "_Test Company UAE VAT"):
+		vat_accounts = frappe.get_all(
+			"Account",
+			fields=["name"],
+			filters = {
+				"company": "_Test Company UAE VAT",
+				"is_group": 0,
+				"account_type": "Tax"
+			}
+		)
+
+		uae_vat_accounts = []
+		for account in vat_accounts:
+			uae_vat_accounts.append({
+				"doctype": "UAE VAT Account",
+				"account": account.name
+			})
+
+		frappe.get_doc({
+			"company": "_Test Company UAE VAT",
+			"uae_vat_accounts": uae_vat_accounts,
+			"doctype": "UAE VAT Settings",
+		}).insert()
+
+def make_customer():
+	if not frappe.db.exists("Customer", "_Test UAE Customer"):
+		customer = frappe.get_doc({
+			"doctype": "Customer",
+			"customer_name": "_Test UAE Customer",
+			"customer_type": "Company",
+		})
+		customer.insert()
+	else:
+		customer = frappe.get_doc("Customer", "_Test UAE Customer")
+
+def make_supplier():
+	if not frappe.db.exists("Supplier", "_Test UAE Supplier"):
+		frappe.get_doc({
+			"supplier_group": "Local",
+			"supplier_name": "_Test UAE Supplier",
+			"supplier_type": "Individual",
+			"doctype": "Supplier",
+		}).insert()
+
+def create_warehouse(warehouse_name, properties=None, company=None):
+	if not company:
+		company = "_Test Company"
+
+	warehouse_id = erpnext.encode_company_abbr(warehouse_name, company)
+	if not frappe.db.exists("Warehouse", warehouse_id):
+		warehouse = frappe.new_doc("Warehouse")
+		warehouse.warehouse_name = warehouse_name
+		warehouse.parent_warehouse = "All Warehouses - _TCUV"
+		warehouse.company = company
+		warehouse.account = get_warehouse_account(warehouse_name, company)
+		if properties:
+			warehouse.update(properties)
+		warehouse.save()
+		return warehouse.name
+	else:
+		return warehouse_id
+
+def make_item(item_code, properties=None):
+	if frappe.db.exists("Item", item_code):
+		return frappe.get_doc("Item", item_code)
+
+	item = frappe.get_doc({
+		"doctype": "Item",
+		"item_code": item_code,
+		"item_name": item_code,
+		"description": item_code,
+		"item_group": "Products"
+	})
+
+	if properties:
+		item.update(properties)
+
+	item.insert()
+
+	return item
+
+def make_sales_invoices():
+	def make_sales_invoices_wrapper(emirate, item, tax = True, tourist_tax= False):
+		si = create_sales_invoice(
+			company="_Test Company UAE VAT",
+			customer = '_Test UAE Customer',
+			currency = 'AED',
+			warehouse = 'Finished Goods - _TCUV',
+			debit_to = 'Debtors - _TCUV',
+			income_account = 'Sales - _TCUV',
+			expense_account = 'Cost of Goods Sold - _TCUV',
+			cost_center = 'Main - _TCUV',
+			item = item,
+			do_not_save=1
+		)
+		si.vat_emirate = emirate
+		if tax:
+			si.append(
+				"taxes", {
+					"charge_type": "On Net Total",
+					"account_head": "VAT 5% - _TCUV",
+					"cost_center": "Main - _TCUV",
+					"description": "VAT 5% @ 5.0",
+					"rate": 5.0
+				}
+			)
+		if tourist_tax:
+			si.tourist_tax_return = 2
+		si.submit()
+
+	#Define Item Names
+	uae_item = "_Test UAE VAT Item"
+	uae_exempt_item = "_Test UAE VAT Exempt Item"
+	uae_zero_rated_item = "_Test UAE VAT Zero Rated Item"
+
+	#Sales Invoice with standard rated expense in Dubai
+	make_sales_invoices_wrapper('Dubai', uae_item)
+	#Sales Invoice with standard rated expense in Sharjah
+	make_sales_invoices_wrapper('Sharjah', uae_item)
+	#Sales Invoice with Tourist Tax Return
+	make_sales_invoices_wrapper('Dubai', uae_item, True, True)
+	#Sales Invoice with Exempt Item
+	make_sales_invoices_wrapper('Sharjah', uae_exempt_item, False)
+	#Sales Invoice with Zero Rated Item
+	make_sales_invoices_wrapper('Sharjah', uae_zero_rated_item, False)
+
+def create_purchase_invoices():
+	pi = make_purchase_invoice(
+		company="_Test Company UAE VAT",
+		supplier = '_Test UAE Supplier',
+		supplier_warehouse = '_Test UAE VAT Supplier Warehouse - _TCUV',
+		warehouse = '_Test UAE VAT Supplier Warehouse - _TCUV',
+		currency = 'AED',
+		cost_center = 'Main - _TCUV',
+		expense_account = 'Cost of Goods Sold - _TCUV',
+		item = "_Test UAE VAT Item",
+		do_not_save=1,
+		uom = "Nos"
+	)
+	pi.append("taxes", {
+		"charge_type": "On Net Total",
+		"account_head": "VAT 5% - _TCUV",
+		"cost_center": "Main - _TCUV",
+		"description": "VAT 5% @ 5.0",
+		"rate": 5.0
+	})
+
+	pi.recoverable_standard_rated_expenses = 1
+
+	pi.submit()
diff --git a/erpnext/regional/report/uae_vat_201/uae_vat_201.html b/erpnext/regional/report/uae_vat_201/uae_vat_201.html
new file mode 100644
index 0000000..d9b9968
--- /dev/null
+++ b/erpnext/regional/report/uae_vat_201/uae_vat_201.html
@@ -0,0 +1,77 @@
+{%
+	var report_columns = report.get_columns_for_print();
+	report_columns = report_columns.filter(col => !col.hidden);
+%}
+<style>
+	.print-format {
+		padding: 10mm;
+		font-size: 8.0pt !important;
+		font-family: Tahoma, sans-serif;
+	}
+</style>
+
+<h1  style="margin-top:0; text-align: center;">{%= __(report.report_name) %}</h1>
+
+<h3  style="margin-top:0; font-weight:500">{%= __("VAT on Sales and All Other Outputs") %}</h2>
+
+<table class="table table-bordered">
+
+    <thead>
+        <th style="width: 13">{%= report_columns[0].label %}</th>
+        <th style="width: {%= 100 - (report_columns.length - 1) * 13%}%">{%= report_columns[1].label %}</th>
+
+        {% for (let i=2; i<report_columns.length; i++) { %}
+            <th style="width: 13">{%= report_columns[i].label %}</th>
+        {% } %}
+    </thead>
+
+    <tbody>
+        {% for (let j=1; j<12; j++)  { %}
+        {%
+            var row = data[j];
+        %}
+        <tr >
+            {% for (let i=0; i<report_columns.length; i++) { %}
+                <td >
+                    {% const fieldname = report_columns[i].fieldname; %}
+                    {% if (!is_null(row[fieldname])) { %}
+                        {%= frappe.format(row[fieldname], report_columns[i], {}, row) %}
+                    {% } %}
+                </td>
+            {% } %}
+        </tr>
+        {% } %}
+    </tbody>
+</table>
+
+<h3 style="margin-top:0; font-weight:500">{%= __("VAT on Expenses and All Other Inputs") %}</h2>
+
+<table  class="table table-bordered">
+    <thead>
+        <th style="width: 13">{%= report_columns[0].label %}</th>
+        <th style="width: {%= 100 - (report_columns.length - 1) * 13%}%">{%= report_columns[1].label %}</th>
+
+        {% for (let i=2; i<report_columns.length; i++) { %}
+            <th style="width: 13">{%= report_columns[i].label %}</th>
+        {% } %}
+    </thead>
+
+    <tbody>
+        {% for (let j=14; j<data.length; j++)  { %}
+        {%
+            var row = data[j];
+        %}
+        <tr >
+            {% for (let i=0; i<report_columns.length; i++) { %}
+                <td >
+                    {% const fieldname = report_columns[i].fieldname; %}
+                    {% if (!is_null(row[fieldname])) { %}
+                        {%= frappe.format(row[fieldname], report_columns[i], {}, row) %}
+                    {% } %}
+                </td>
+            {% } %}
+        </tr>
+        {% } %}
+    </tbody>
+
+</table>
\ No newline at end of file
diff --git a/erpnext/regional/report/uae_vat_201/uae_vat_201.js b/erpnext/regional/report/uae_vat_201/uae_vat_201.js
new file mode 100644
index 0000000..5957424
--- /dev/null
+++ b/erpnext/regional/report/uae_vat_201/uae_vat_201.js
@@ -0,0 +1,40 @@
+// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+/* eslint-disable */
+
+frappe.query_reports["UAE VAT 201"] = {
+	"filters": [
+		{
+			"fieldname": "company",
+			"label": __("Company"),
+			"fieldtype": "Link",
+			"options": "Company",
+			"reqd": 1,
+			"default": frappe.defaults.get_user_default("Company")
+		},
+		{
+			"fieldname": "from_date",
+			"label": __("From Date"),
+			"fieldtype": "Date",
+			"reqd": 1,
+			"default": frappe.datetime.add_months(frappe.datetime.get_today(), -3),
+		},
+		{
+			"fieldname": "to_date",
+			"label": __("To Date"),
+			"fieldtype": "Date",
+			"reqd": 1,
+			"default": frappe.datetime.get_today()
+		},
+	],
+	"formatter": function(value, row, column, data, default_formatter) {
+		if (data
+			&& (data.legend=='VAT on Sales and All Other Outputs' || data.legend=='VAT on Expenses and All Other Inputs')
+			&& data.legend==value) {
+			value = $(`<span>${value}</span>`);
+			var $value = $(value).css("font-weight", "bold");
+			value = $value.wrap("<p></p>").parent().html();
+		}
+		return value;
+	},
+};
diff --git a/erpnext/regional/report/uae_vat_201/uae_vat_201.json b/erpnext/regional/report/uae_vat_201/uae_vat_201.json
new file mode 100644
index 0000000..8a88bcd
--- /dev/null
+++ b/erpnext/regional/report/uae_vat_201/uae_vat_201.json
@@ -0,0 +1,22 @@
+{
+ "add_total_row": 0,
+ "columns": [],
+ "creation": "2020-09-10 08:51:02.298482",
+ "disable_prepared_report": 0,
+ "disabled": 0,
+ "docstatus": 0,
+ "doctype": "Report",
+ "filters": [],
+ "idx": 0,
+ "is_standard": "Yes",
+ "modified": "2020-09-10 08:51:02.298482",
+ "modified_by": "Administrator",
+ "module": "Regional",
+ "name": "UAE VAT 201",
+ "owner": "Administrator",
+ "prepared_report": 0,
+ "ref_doctype": "GL Entry",
+ "report_name": "UAE VAT 201",
+ "report_type": "Script Report",
+ "roles": []
+}
\ No newline at end of file
diff --git a/erpnext/regional/report/uae_vat_201/uae_vat_201.py b/erpnext/regional/report/uae_vat_201/uae_vat_201.py
new file mode 100644
index 0000000..b061423
--- /dev/null
+++ b/erpnext/regional/report/uae_vat_201/uae_vat_201.py
@@ -0,0 +1,339 @@
+# 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):
+	columns = get_columns()
+	data, emirates, amounts_by_emirate = get_data(filters)
+	return columns, data
+
+def get_columns():
+	"""Creates a list of dictionaries that are used to generate column headers of the data table."""
+	return [
+		{
+			"fieldname": "no",
+			"label": _("No"),
+			"fieldtype": "Data",
+			"width": 50
+		},
+		{
+			"fieldname": "legend",
+			"label": _("Legend"),
+			"fieldtype": "Data",
+			"width": 300
+		},
+		{
+			"fieldname": "amount",
+			"label": _("Amount (AED)"),
+			"fieldtype": "Currency",
+			"width": 125,
+		},
+		{
+			"fieldname": "vat_amount",
+			"label": _("VAT Amount (AED)"),
+			"fieldtype": "Currency",
+			"width": 150,
+		}
+	]
+
+def get_data(filters = None):
+	"""Returns the list of dictionaries. Each dictionary is a row in the datatable and chart data."""
+	data = []
+	emirates, amounts_by_emirate = append_vat_on_sales(data, filters)
+	append_vat_on_expenses(data, filters)
+	return data, emirates, amounts_by_emirate
+
+def append_vat_on_sales(data, filters):
+	"""Appends Sales and All Other Outputs."""
+	append_data(data, '', _('VAT on Sales and All Other Outputs'), '', '')
+
+	emirates, amounts_by_emirate = standard_rated_expenses_emiratewise(data, filters)
+
+	append_data(data, '2',
+		 _('Tax Refunds provided to Tourists under the Tax Refunds for Tourists Scheme'),
+		frappe.format((-1) * get_tourist_tax_return_total(filters), 'Currency'),
+		frappe.format((-1) * get_tourist_tax_return_tax(filters), 'Currency'))
+
+	append_data(data, '3', _('Supplies subject to the reverse charge provision'),
+		frappe.format(get_reverse_charge_total(filters), 'Currency'),
+		frappe.format(get_reverse_charge_tax(filters), 'Currency'))
+
+	append_data(data, '4', _('Zero Rated'),
+		frappe.format(get_zero_rated_total(filters), 'Currency'), "-")
+
+	append_data(data, '5', _('Exempt Supplies'),
+		frappe.format(get_exempt_total(filters), 'Currency'),"-")
+
+	append_data(data, '', '', '', '')
+
+	return emirates, amounts_by_emirate
+
+def standard_rated_expenses_emiratewise(data, filters):
+	"""Append emiratewise standard rated expenses and vat."""
+	total_emiratewise = get_total_emiratewise(filters)
+	emirates = get_emirates()
+	amounts_by_emirate = {}
+	for emirate, amount, vat in total_emiratewise:
+		amounts_by_emirate[emirate] = {
+			"legend": emirate,
+			"raw_amount": amount,
+			"raw_vat_amount": vat,
+			"amount": frappe.format(amount, 'Currency'),
+			"vat_amount": frappe.format(vat, 'Currency'),
+		}
+	amounts_by_emirate = append_emiratewise_expenses(data, emirates, amounts_by_emirate)
+	return emirates, amounts_by_emirate
+
+def append_emiratewise_expenses(data, emirates, amounts_by_emirate):
+	"""Append emiratewise standard rated expenses and vat."""
+	for no, emirate in enumerate(emirates, 97):
+		if emirate in amounts_by_emirate:
+			amounts_by_emirate[emirate]["no"] = _('1{0}').format(chr(no))
+			amounts_by_emirate[emirate]["legend"] = _('Standard rated supplies in {0}').format(emirate)
+			data.append(amounts_by_emirate[emirate])
+		else:
+			append_data(data, _('1{0}').format(chr(no)),
+				_('Standard rated supplies in {0}').format(emirate),
+				frappe.format(0, 'Currency'), frappe.format(0, 'Currency'))
+	return amounts_by_emirate
+
+def append_vat_on_expenses(data, filters):
+	"""Appends Expenses and All Other Inputs."""
+	append_data(data, '', _('VAT on Expenses and All Other Inputs'), '', '')
+	append_data(data, '9', _('Standard Rated Expenses'),
+		frappe.format(get_standard_rated_expenses_total(filters), 'Currency'),
+		frappe.format(get_standard_rated_expenses_tax(filters), 'Currency'))
+	append_data(data, '10', _('Supplies subject to the reverse charge provision'),
+		frappe.format(get_reverse_charge_recoverable_total(filters), 'Currency'),
+		frappe.format(get_reverse_charge_recoverable_tax(filters), 'Currency'))
+
+def append_data(data, no, legend, amount, vat_amount):
+	"""Returns data with appended value."""
+	data.append({"no": no, "legend":legend, "amount": amount, "vat_amount": vat_amount})
+
+def get_total_emiratewise(filters):
+	"""Returns Emiratewise Amount and Taxes."""
+	conditions = get_conditions(filters)
+	try:
+		return frappe.db.sql("""
+			select
+				s.vat_emirate as emirate, sum(i.base_amount) as total, sum(s.total_taxes_and_charges)
+			from
+				`tabSales Invoice Item` i inner join `tabSales Invoice` s
+			on
+				i.parent = s.name
+			where
+				s.docstatus = 1 and  i.is_exempt != 1 and i.is_zero_rated != 1
+				{where_conditions}
+			group by
+				s.vat_emirate;
+			""".format(where_conditions=conditions), filters)
+	except (IndexError, TypeError):
+		return 0
+
+def get_emirates():
+	"""Returns a List of emirates in the order that they are to be displayed."""
+	return [
+		'Abu Dhabi',
+		'Dubai',
+		'Sharjah',
+		'Ajman',
+		'Umm Al Quwain',
+		'Ras Al Khaimah',
+		'Fujairah'
+	]
+
+def get_filters(filters):
+	"""The conditions to be used to filter data to calculate the total sale."""
+	query_filters = []
+	if filters.get("company"):
+		query_filters.append(["company", '=', filters['company']])
+	if filters.get("from_date"):
+		query_filters.append(["posting_date", '>=', filters['from_date']])
+	if filters.get("from_date"):
+		query_filters.append(["posting_date", '<=', filters['to_date']])
+	return query_filters
+
+def get_reverse_charge_total(filters):
+	"""Returns the sum of the total of each Purchase invoice made."""
+	query_filters = get_filters(filters)
+	query_filters.append(['reverse_charge', '=', 'Y'])
+	query_filters.append(['docstatus', '=', 1])
+	try:
+		return frappe.db.get_all('Purchase Invoice',
+			filters = query_filters,
+			fields = ['sum(total)'],
+			as_list=True,
+			limit = 1
+		)[0][0] or 0
+	except (IndexError, TypeError):
+		return 0
+
+def get_reverse_charge_tax(filters):
+	"""Returns the sum of the tax of each Purchase invoice made."""
+	conditions = get_conditions_join(filters)
+	return frappe.db.sql("""
+		select sum(debit)  from
+			`tabPurchase Invoice` p inner join `tabGL Entry` gl
+		on
+			gl.voucher_no =  p.name
+		where
+			p.reverse_charge = "Y"
+			and p.docstatus = 1
+			and gl.docstatus = 1
+			and account in (select account from `tabUAE VAT Account` where  parent=%(company)s)
+			{where_conditions} ;
+		""".format(where_conditions=conditions), filters)[0][0] or 0
+
+def get_reverse_charge_recoverable_total(filters):
+	"""Returns the sum of the total of each Purchase invoice made with recoverable reverse charge."""
+	query_filters = get_filters(filters)
+	query_filters.append(['reverse_charge', '=', 'Y'])
+	query_filters.append(['recoverable_reverse_charge', '>', '0'])
+	query_filters.append(['docstatus', '=', 1])
+	try:
+		return frappe.db.get_all('Purchase Invoice',
+			filters = query_filters,
+			fields = ['sum(total)'],
+			as_list=True,
+			limit = 1
+		)[0][0] or 0
+	except (IndexError, TypeError):
+		return 0
+
+def get_reverse_charge_recoverable_tax(filters):
+	"""Returns the sum of the tax of each Purchase invoice made."""
+	conditions = get_conditions_join(filters)
+	return frappe.db.sql("""
+		select
+			sum(debit * p.recoverable_reverse_charge / 100)
+		from
+			`tabPurchase Invoice` p  inner join `tabGL Entry` gl
+		on
+			gl.voucher_no = p.name
+		where
+			p.reverse_charge = "Y"
+			and p.docstatus = 1
+			and p.recoverable_reverse_charge > 0
+			and gl.docstatus = 1
+			and account in (select account from `tabUAE VAT Account` where  parent=%(company)s)
+			{where_conditions} ;
+		""".format(where_conditions=conditions), filters)[0][0] or 0
+
+def get_conditions_join(filters):
+	"""The conditions to be used to filter data to calculate the total vat."""
+	conditions = ""
+	for opts in (("company", " and p.company=%(company)s"),
+		("from_date", " and p.posting_date>=%(from_date)s"),
+		("to_date", " and p.posting_date<=%(to_date)s")):
+		if filters.get(opts[0]):
+			conditions += opts[1]
+	return conditions
+
+def get_standard_rated_expenses_total(filters):
+	"""Returns the sum of the total of each Purchase invoice made with recoverable reverse charge."""
+	query_filters = get_filters(filters)
+	query_filters.append(['recoverable_standard_rated_expenses', '>', 0])
+	query_filters.append(['docstatus', '=', 1])
+	try:
+		return frappe.db.get_all('Purchase Invoice',
+			filters = query_filters,
+			fields = ['sum(total)'],
+			as_list=True,
+			limit = 1
+		)[0][0]  or 0
+	except (IndexError, TypeError):
+		return 0
+
+def get_standard_rated_expenses_tax(filters):
+	"""Returns the sum of the tax of each Purchase invoice made."""
+	query_filters = get_filters(filters)
+	query_filters.append(['recoverable_standard_rated_expenses', '>', 0])
+	query_filters.append(['docstatus', '=', 1])
+	try:
+		return frappe.db.get_all('Purchase Invoice',
+			filters = query_filters,
+			fields = ['sum(recoverable_standard_rated_expenses)'],
+			as_list=True,
+			limit = 1
+		)[0][0]  or 0
+	except (IndexError, TypeError):
+		return 0
+
+def get_tourist_tax_return_total(filters):
+	"""Returns the sum of the total of each Sales invoice with non zero tourist_tax_return."""
+	query_filters = get_filters(filters)
+	query_filters.append(['tourist_tax_return', '>', 0])
+	query_filters.append(['docstatus', '=', 1])
+	try:
+		return frappe.db.get_all('Sales Invoice',
+			filters = query_filters,
+			fields = ['sum(total)'],
+			as_list=True,
+			limit = 1
+		)[0][0]  or 0
+	except (IndexError, TypeError):
+		return 0
+
+def get_tourist_tax_return_tax(filters):
+	"""Returns the sum of the tax of each Sales invoice with non zero tourist_tax_return."""
+	query_filters = get_filters(filters)
+	query_filters.append(['tourist_tax_return', '>', 0])
+	query_filters.append(['docstatus', '=', 1])
+	try:
+		return frappe.db.get_all('Sales Invoice',
+			filters = query_filters,
+			fields = ['sum(tourist_tax_return)'],
+			as_list=True,
+			limit = 1
+		)[0][0]  or 0
+	except (IndexError, TypeError):
+		return 0
+
+def get_zero_rated_total(filters):
+	"""Returns the sum of each Sales Invoice Item Amount which is zero rated."""
+	conditions = get_conditions(filters)
+	try:
+		return frappe.db.sql("""
+			select
+				sum(i.base_amount) as total
+			from
+				`tabSales Invoice Item` i inner join `tabSales Invoice` s
+			on
+				i.parent = s.name
+			where
+				s.docstatus = 1 and  i.is_zero_rated = 1
+				{where_conditions} ;
+			""".format(where_conditions=conditions), filters)[0][0] or 0
+	except (IndexError, TypeError):
+		return 0
+
+def get_exempt_total(filters):
+	"""Returns the sum of each Sales Invoice Item Amount which is Vat Exempt."""
+	conditions = get_conditions(filters)
+	try:
+		return frappe.db.sql("""
+			select
+				sum(i.base_amount) as total
+			from
+				`tabSales Invoice Item` i inner join `tabSales Invoice` s
+			on
+				i.parent = s.name
+			where
+				s.docstatus = 1 and  i.is_exempt = 1
+				{where_conditions} ;
+			""".format(where_conditions=conditions), filters)[0][0] or 0
+	except (IndexError, TypeError):
+		return 0
+def get_conditions(filters):
+	"""The conditions to be used to filter data to calculate the total sale."""
+	conditions = ""
+	for opts in (("company", " and company=%(company)s"),
+		("from_date", " and posting_date>=%(from_date)s"),
+		("to_date", " and posting_date<=%(to_date)s")):
+		if filters.get(opts[0]):
+			conditions += opts[1]
+	return conditions
diff --git a/erpnext/regional/united_arab_emirates/setup.py b/erpnext/regional/united_arab_emirates/setup.py
index 250659e..013ae5c 100644
--- a/erpnext/regional/united_arab_emirates/setup.py
+++ b/erpnext/regional/united_arab_emirates/setup.py
@@ -5,24 +5,30 @@
 
 import frappe, os, json
 from frappe.custom.doctype.custom_field.custom_field import create_custom_fields
+from frappe.permissions import add_permission, update_permission_property
 from erpnext.setup.setup_wizard.operations.taxes_setup import create_sales_tax
 
 def setup(company=None, patch=True):
 	make_custom_fields()
 	add_print_formats()
-
+	add_custom_roles_for_reports()
+	add_permissions()
 	if company:
 		create_sales_tax(company)
 
 def make_custom_fields():
+	is_zero_rated = dict(fieldname='is_zero_rated', label='Is Zero Rated',
+		fieldtype='Check', fetch_from='item_code.is_zero_rated', insert_after='description',
+		print_hide=1)
+	is_exempt = dict(fieldname='is_exempt', label='Is Exempt',
+		fieldtype='Check', fetch_from='item_code.is_exempt', insert_after='is_zero_rated',
+		print_hide=1)
+
 	invoice_fields = [
 		dict(fieldname='vat_section', label='VAT Details', fieldtype='Section Break',
 			insert_after='group_same_items', print_hide=1, collapsible=1),
 		dict(fieldname='permit_no', label='Permit Number',
 			fieldtype='Data', insert_after='vat_section', print_hide=1),
-		dict(fieldname='reverse_charge_applicable', label='Reverse Charge Applicable',
-			fieldtype='Select', insert_after='permit_no', print_hide=1,
-			options='Y\nN', default='N')
 	]
 
 	purchase_invoice_fields = [
@@ -31,7 +37,16 @@
 				fetch_from='company.tax_id', print_hide=1),
 			dict(fieldname='supplier_name_in_arabic', label='Supplier Name in Arabic',
 				fieldtype='Read Only', insert_after='supplier_name',
-				fetch_from='supplier.supplier_name_in_arabic', print_hide=1)
+				fetch_from='supplier.supplier_name_in_arabic', print_hide=1),
+			dict(fieldname='recoverable_standard_rated_expenses', print_hide=1, default='0',
+				label='Recoverable Standard Rated Expenses (AED)', insert_after='permit_no',
+				fieldtype='Currency', ),
+			dict(fieldname='reverse_charge', label='Reverse Charge Applicable',
+				fieldtype='Select', insert_after='recoverable_standard_rated_expenses', print_hide=1,
+				options='Y\nN', default='N'),
+			dict(fieldname='recoverable_reverse_charge', label='Recoverable Reverse Charge (Percentage)',
+				insert_after='reverse_charge', fieldtype='Percent', print_hide=1,
+				depends_on="eval:doc.reverse_charge=='Y'", default='100.000'),
 		]
 
 	sales_invoice_fields = [
@@ -41,6 +56,11 @@
 			dict(fieldname='customer_name_in_arabic', label='Customer Name in Arabic',
 				fieldtype='Read Only', insert_after='customer_name',
 				fetch_from='customer.customer_name_in_arabic', print_hide=1),
+			dict(fieldname='vat_emirate', label='VAT Emirate', insert_after='permit_no', fieldtype='Select',
+				options='\nAbu Dhabi\nAjman\nDubai\nFujairah\nRas Al Khaimah\nSharjah\nUmm Al Quwain',
+				fetch_from='company_address.emirate'),
+			dict(fieldname='tourist_tax_return', label='Tax Refund provided to Tourists (AED)',
+				insert_after='vat_emirate', fieldtype='Currency', print_hide=1, default='0'),
 		]
 
 	invoice_item_fields = [
@@ -67,6 +87,12 @@
 		'Item': [
 			dict(fieldname='tax_code', label='Tax Code',
 				fieldtype='Data', insert_after='item_group'),
+			dict(fieldname='is_zero_rated', label='Is Zero Rated',
+				fieldtype='Check', insert_after='tax_code',
+				print_hide=1),
+			dict(fieldname='is_exempt', label='Is Exempt',
+				fieldtype='Check', insert_after='is_zero_rated',
+				print_hide=1)
 		],
 		'Customer': [
 			dict(fieldname='customer_name_in_arabic', label='Customer Name in Arabic',
@@ -76,13 +102,17 @@
 			dict(fieldname='supplier_name_in_arabic', label='Supplier Name in Arabic',
 				fieldtype='Data', insert_after='supplier_name'),
 		],
+		'Address': [
+			dict(fieldname='emirate', label='Emirate', fieldtype='Select', insert_after='state',
+			options='\nAbu Dhabi\nAjman\nDubai\nFujairah\nRas Al Khaimah\nSharjah\nUmm Al Quwain')
+		],
 		'Purchase Invoice': purchase_invoice_fields + invoice_fields,
 		'Purchase Order': purchase_invoice_fields + invoice_fields,
 		'Purchase Receipt': purchase_invoice_fields + invoice_fields,
 		'Sales Invoice': sales_invoice_fields + invoice_fields,
 		'Sales Order': sales_invoice_fields + invoice_fields,
 		'Delivery Note': sales_invoice_fields + invoice_fields,
-		'Sales Invoice Item': invoice_item_fields + delivery_date_field,
+		'Sales Invoice Item': invoice_item_fields + delivery_date_field + [is_zero_rated, is_exempt],
 		'Purchase Invoice Item': invoice_item_fields,
 		'Sales Order Item': invoice_item_fields,
 		'Delivery Note Item': invoice_item_fields,
@@ -101,3 +131,25 @@
 
 	frappe.db.sql(""" update `tabPrint Format` set disabled = 0 where
 		name in('Simplified Tax Invoice', 'Detailed Tax Invoice', 'Tax Invoice') """)
+
+def add_custom_roles_for_reports():
+	"""Add Access Control to UAE VAT 201."""
+	if not frappe.db.get_value('Custom Role', dict(report='UAE VAT 201')):
+		frappe.get_doc(dict(
+			doctype='Custom Role',
+			report='UAE VAT 201',
+			roles= [
+				dict(role='Accounts User'),
+				dict(role='Accounts Manager'),
+				dict(role='Auditor')
+			]
+		)).insert()
+
+def add_permissions():
+	"""Add Permissions for UAE VAT Settings and UAE VAT Account."""
+	for doctype in ('UAE VAT Settings', 'UAE VAT Account'):
+		add_permission(doctype, 'All', 0)
+		for role in ('Accounts Manager', 'Accounts User', 'System Manager'):
+			add_permission(doctype, role, 0)
+			update_permission_property(doctype, role, 0, 'write', 1)
+			update_permission_property(doctype, role, 0, 'create', 1)
diff --git a/erpnext/regional/united_arab_emirates/utils.py b/erpnext/regional/united_arab_emirates/utils.py
index a0425f6..7d5fd6e 100644
--- a/erpnext/regional/united_arab_emirates/utils.py
+++ b/erpnext/regional/united_arab_emirates/utils.py
@@ -1,6 +1,8 @@
 from __future__ import unicode_literals
 import frappe
-from frappe.utils import flt
+from frappe import _
+import erpnext
+from frappe.utils import flt, round_based_on_smallest_currency_fraction, money_in_words
 from erpnext.controllers.taxes_and_totals import get_itemised_tax
 from six import iteritems
 
@@ -26,4 +28,134 @@
 
 		row.tax_rate = flt(tax_rate, row.precision("tax_rate"))
 		row.tax_amount = flt((row.net_amount * tax_rate) / 100, row.precision("net_amount"))
-		row.total_amount = flt((row.net_amount + row.tax_amount), row.precision("total_amount"))
\ No newline at end of file
+		row.total_amount = flt((row.net_amount + row.tax_amount), row.precision("total_amount"))
+
+def get_account_currency(account):
+	"""Helper function to get account currency."""
+	if not account:
+		return
+	def generator():
+		account_currency, company = frappe.get_cached_value(
+			"Account",
+			account,
+			["account_currency",
+			"company"]
+		)
+		if not account_currency:
+			account_currency = frappe.get_cached_value('Company',  company,  "default_currency")
+
+		return account_currency
+
+	return frappe.local_cache("account_currency", account, generator)
+
+def get_tax_accounts(company):
+	"""Get the list of tax accounts for a specific company."""
+	tax_accounts_dict = frappe._dict()
+	tax_accounts_list = frappe.get_all("UAE VAT Account",
+		filters={"parent": company},
+		fields=["Account"]
+		)
+
+	if not tax_accounts_list and not frappe.flags.in_test:
+		frappe.throw(_('Please set Vat Accounts for Company: "{0}" in UAE VAT Settings').format(company))
+	for tax_account in tax_accounts_list:
+		for account, name in tax_account.items():
+			tax_accounts_dict[name] = name
+
+	return tax_accounts_dict
+
+def update_grand_total_for_rcm(doc, method):
+	"""If the Reverse Charge is Applicable subtract the tax amount from the grand total and update in the form."""
+	country = frappe.get_cached_value('Company', doc.company, 'country')
+
+	if country != 'United Arab Emirates':
+		return
+
+	if not doc.total_taxes_and_charges:
+		return
+
+	if doc.reverse_charge == 'Y':
+		tax_accounts = get_tax_accounts(doc.company)
+
+		base_vat_tax = 0
+		vat_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 tax_accounts:
+				base_vat_tax += tax.base_tax_amount_after_discount_amount
+				vat_tax += tax.tax_amount_after_discount_amount
+
+		doc.taxes_and_charges_added -= vat_tax
+		doc.total_taxes_and_charges -= vat_tax
+		doc.base_taxes_and_charges_added -= base_vat_tax
+		doc.base_total_taxes_and_charges -= base_vat_tax
+
+		update_totals(vat_tax, base_vat_tax, doc)
+
+def update_totals(vat_tax, base_vat_tax, doc):
+	"""Update the grand total values in the form."""
+	doc.base_grand_total -= base_vat_tax
+	doc.grand_total -= vat_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.base_in_words = money_in_words(doc.base_grand_total, erpnext.get_company_currency(doc.company))
+	doc.set_payment_schedule()
+
+def make_regional_gl_entries(gl_entries, doc):
+	"""Hooked to make_regional_gl_entries in Purchase Invoice.It appends the region specific general ledger entries to the list of GL Entries."""
+	country = frappe.get_cached_value('Company', doc.company, 'country')
+
+	if country != 'United Arab Emirates':
+		return gl_entries
+
+	if doc.reverse_charge == 'Y':
+		tax_accounts = get_tax_accounts(doc.company)
+		for tax in doc.get('taxes'):
+			if tax.category not in ("Total", "Valuation and Total"):
+				continue
+			gl_entries = make_gl_entry(tax, gl_entries, doc, tax_accounts)
+	return gl_entries
+
+def make_gl_entry(tax, gl_entries, doc, tax_accounts):
+	dr_or_cr = "credit" if tax.add_deduct_tax == "Add" else "debit"
+	if flt(tax.base_tax_amount_after_discount_amount)  and tax.account_head in tax_accounts:
+		account_currency = get_account_currency(tax.account_head)
+
+		gl_entries.append(doc.get_gl_dict({
+				"account": tax.account_head,
+				"cost_center": tax.cost_center,
+				"posting_date": doc.posting_date,
+				"against": doc.supplier,
+				dr_or_cr: tax.base_tax_amount_after_discount_amount,
+				dr_or_cr + "_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=tax
+		))
+	return gl_entries
+
+
+def validate_returns(doc, method):
+	"""Standard Rated expenses should not be set when Reverse Charge Applicable is set."""
+	country = frappe.get_cached_value('Company', doc.company, 'country')
+	if country != 'United Arab Emirates':
+		return
+	if doc.reverse_charge == 'Y' and  flt(doc.recoverable_standard_rated_expenses) != 0:
+		frappe.throw(_(
+			"Recoverable Standard Rated expenses should not be set when Reverse Charge Applicable is Y"
+		))
diff --git a/erpnext/selling/doctype/quotation/quotation.js b/erpnext/selling/doctype/quotation/quotation.js
index 12f3260..661e107 100644
--- a/erpnext/selling/doctype/quotation/quotation.js
+++ b/erpnext/selling/doctype/quotation/quotation.js
@@ -116,7 +116,7 @@
 							company: me.frm.doc.company
 						}
 					})
-				}, __("Get items from"), "btn-default");
+				}, __("Get Items From"), "btn-default");
 		}
 
 		this.toggle_reqd_lead_customer();
diff --git a/erpnext/selling/doctype/quotation/quotation.json b/erpnext/selling/doctype/quotation/quotation.json
index 5b85187..3eba62b 100644
--- a/erpnext/selling/doctype/quotation/quotation.json
+++ b/erpnext/selling/doctype/quotation/quotation.json
@@ -1,5 +1,6 @@
 {
  "actions": [],
+ "allow_auto_repeat": 1,
  "allow_import": 1,
  "autoname": "naming_series:",
  "creation": "2013-05-24 19:29:08",
@@ -932,7 +933,7 @@
  "is_submittable": 1,
  "links": [],
  "max_attachments": 1,
- "modified": "2020-07-26 17:46:19.951223",
+ "modified": "2020-10-30 13:58:59.212060",
  "modified_by": "Administrator",
  "module": "Selling",
  "name": "Quotation",
diff --git a/erpnext/selling/doctype/sales_order/sales_order.js b/erpnext/selling/doctype/sales_order/sales_order.js
index f162291..1d890bb 100644
--- a/erpnext/selling/doctype/sales_order/sales_order.js
+++ b/erpnext/selling/doctype/sales_order/sales_order.js
@@ -236,7 +236,7 @@
 							status: ["!=", "Lost"]
 						}
 					})
-				}, __("Get items from"));
+				}, __("Get Items From"));
 		}
 
 		this.order_type(doc);
@@ -326,8 +326,7 @@
 								callback: function(r) {
 									if(r.message) {
 										frappe.msgprint({
-											message: __('Work Orders Created: {0}',
-												[r.message.map(function(d) {
+											message: __('Work Orders Created: {0}', [r.message.map(function(d) {
 													return repl('<a href="#Form/Work Order/%(name)s">%(name)s</a>', {name:d})
 												}).join(', ')]),
 											indicator: 'green'
diff --git a/erpnext/selling/doctype/sales_order/sales_order.json b/erpnext/selling/doctype/sales_order/sales_order.json
index 77c1787..3d64ac3 100644
--- a/erpnext/selling/doctype/sales_order/sales_order.json
+++ b/erpnext/selling/doctype/sales_order/sales_order.json
@@ -1,5 +1,6 @@
 {
  "actions": [],
+ "allow_auto_repeat": 1,
  "allow_import": 1,
  "autoname": "naming_series:",
  "creation": "2013-06-18 12:39:59",
@@ -1460,7 +1461,7 @@
  "idx": 105,
  "is_submittable": 1,
  "links": [],
- "modified": "2020-10-07 14:30:01.782617",
+ "modified": "2020-10-30 13:59:18.628077",
  "modified_by": "Administrator",
  "module": "Selling",
  "name": "Sales Order",
diff --git a/erpnext/selling/doctype/sales_order/sales_order.py b/erpnext/selling/doctype/sales_order/sales_order.py
index ec1c823..04d85e5 100755
--- a/erpnext/selling/doctype/sales_order/sales_order.py
+++ b/erpnext/selling/doctype/sales_order/sales_order.py
@@ -844,7 +844,8 @@
 						"contact_email",
 						"contact_person",
 						"taxes_and_charges",
-						"shipping_address"
+						"shipping_address",
+						"terms"
 					],
 					"validation": {
 						"docstatus": ["=", 1]
@@ -863,7 +864,10 @@
 					"field_no_map": [
 						"rate",
 						"price_list_rate",
-						"item_tax_template"
+						"item_tax_template",
+						"discount_percentage",
+						"discount_amount",
+						"pricing_rules"
 					],
 					"postprocess": update_item,
 					"condition": lambda doc: doc.ordered_qty < doc.stock_qty and doc.supplier == supplier and doc.item_code in items_to_map
@@ -917,7 +921,8 @@
 				"contact_email",
 				"contact_person",
 				"taxes_and_charges",
-				"shipping_address"
+				"shipping_address",
+				"terms"
 			],
 			"validation": {
 				"docstatus": ["=", 1]
@@ -937,7 +942,10 @@
 				"rate",
 				"price_list_rate",
 				"item_tax_template",
-				"supplier"
+				"discount_percentage",
+				"discount_amount",
+				"supplier",
+				"pricing_rules"
 			],
 			"postprocess": update_item,
 			"condition": lambda doc: doc.ordered_qty < doc.stock_qty and doc.item_code in items_to_map
diff --git a/erpnext/selling/doctype/sales_order/test_sales_order.py b/erpnext/selling/doctype/sales_order/test_sales_order.py
index a33d401..643e7cf 100644
--- a/erpnext/selling/doctype/sales_order/test_sales_order.py
+++ b/erpnext/selling/doctype/sales_order/test_sales_order.py
@@ -1064,6 +1064,7 @@
 	so.company = args.company or "_Test Company"
 	so.customer = args.customer or "_Test Customer"
 	so.currency = args.currency or "INR"
+	so.po_no = args.po_no or '12345'
 	if args.selling_price_list:
 		so.selling_price_list = args.selling_price_list
 
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 a690050..062cba1 100644
--- a/erpnext/selling/page/point_of_sale/point_of_sale.py
+++ b/erpnext/selling/page/point_of_sale/point_of_sale.py
@@ -62,6 +62,7 @@
 			`tabItem` item {bin_join_selection}
 		WHERE
 			item.disabled = 0
+			AND item.is_stock_item = 1
 			AND item.has_variants = 0
 			AND item.is_sales_item = 1
 			AND item.is_fixed_asset = 0
diff --git a/erpnext/selling/page/point_of_sale/pos_controller.js b/erpnext/selling/page/point_of_sale/pos_controller.js
index f7d1fa4..ad1633e 100644
--- a/erpnext/selling/page/point_of_sale/pos_controller.js
+++ b/erpnext/selling/page/point_of_sale/pos_controller.js
@@ -555,6 +555,8 @@
 					frappe.utils.play_sound("error");
 					return;
 				}
+				if (!item_code) return;
+
 				item_selected_from_selector && (value = flt(value))
 
 				const args = { item_code, batch_no, [field]: value };
@@ -642,8 +644,7 @@
 			})
 		} else if (available_qty < qty_needed) {
 			frappe.show_alert({
-				message: __('Stock quantity not enough for Item Code: {0} under warehouse {1}. Available quantity {2}.',
-					[bold_item_code, bold_warehouse, bold_available_qty]),
+				message: __('Stock quantity not enough for Item Code: {0} under warehouse {1}. Available quantity {2}.', [bold_item_code, bold_warehouse, bold_available_qty]),
 				indicator: 'orange'
 			});
 			frappe.utils.play_sound("error");
diff --git a/erpnext/selling/page/point_of_sale/pos_item_details.js b/erpnext/selling/page/point_of_sale/pos_item_details.js
index 9874d1b..a4de9f1 100644
--- a/erpnext/selling/page/point_of_sale/pos_item_details.js
+++ b/erpnext/selling/page/point_of_sale/pos_item_details.js
@@ -372,12 +372,13 @@
 		this.$form_container.on('click', '.auto-fetch-btn', () => {
 			this.batch_no_control && this.batch_no_control.set_value('');
 			let qty = this.qty_control.get_value();
+			let conversion_factor = this.conversion_factor_control.get_value();
 			let expiry_date = this.item_row.has_batch_no ? this.events.get_frm().doc.posting_date : "";
 
 			let numbers = frappe.call({
 				method: "erpnext.stock.doctype.serial_no.serial_no.auto_fetch_serial_number",
 				args: {
-					qty,
+					qty: qty * conversion_factor,
 					item_code: this.current_item.item_code,
 					warehouse: this.warehouse_control.get_value() || '',
 					batch_nos: this.current_item.batch_no || '',
diff --git a/erpnext/selling/sales_common.js b/erpnext/selling/sales_common.js
index 002cfe4..7f00fca 100644
--- a/erpnext/selling/sales_common.js
+++ b/erpnext/selling/sales_common.js
@@ -42,16 +42,6 @@
 		me.frm.set_query('customer_address', erpnext.queries.address_query);
 		me.frm.set_query('shipping_address_name', erpnext.queries.address_query);
 
-		if(this.frm.fields_dict.taxes_and_charges) {
-			this.frm.set_query("taxes_and_charges", function() {
-				return {
-					filters: [
-						['Sales Taxes and Charges Template', 'company', '=', me.frm.doc.company],
-						['Sales Taxes and Charges Template', 'docstatus', '!=', 2]
-					]
-				}
-			});
-		}
 
 		if(this.frm.fields_dict.selling_price_list) {
 			this.frm.set_query("selling_price_list", function() {
@@ -479,7 +469,7 @@
 						$.each(frm.doc["items"] || [], function(i, row) {
 							if(r.message) {
 								frappe.model.set_value(row.doctype, row.name, "cost_center", r.message);
-								frappe.msgprint(__("Cost Center For Item with Item Code '"+row.item_name+"' has been Changed to "+ r.message));
+								frappe.msgprint(__("Cost Center For Item with Item Code {0} has been Changed to {1}", [row.item_name, r.message]));
 							}
 						})
 					}
diff --git a/erpnext/setup/doctype/company/company.js b/erpnext/setup/doctype/company/company.js
index f882db6..cbf67b4 100644
--- a/erpnext/setup/doctype/company/company.js
+++ b/erpnext/setup/doctype/company/company.js
@@ -90,29 +90,41 @@
 			frm.toggle_enable("default_currency", (frm.doc.__onload &&
 				!frm.doc.__onload.transactions_exist));
 
-			frm.add_custom_button(__('Create Tax Template'), function() {
-				frm.trigger("make_default_tax_template");
-			});
+			if (frm.has_perm('write')) {
+				frm.add_custom_button(__('Create Tax Template'), function() {
+					frm.trigger("make_default_tax_template");
+				});
+			}
 
-			frm.add_custom_button(__('Cost Centers'), function() {
-				frappe.set_route('Tree', 'Cost Center', {'company': frm.doc.name})
-			}, __("View"));
+			if (frappe.perm.has_perm("Cost Center", 0, 'read')) {
+				frm.add_custom_button(__('Cost Centers'), function() {
+					frappe.set_route('Tree', 'Cost Center', {'company': frm.doc.name});
+				}, __("View"));
+			}
 
-			frm.add_custom_button(__('Chart of Accounts'), function() {
-				frappe.set_route('Tree', 'Account', {'company': frm.doc.name})
-			}, __("View"));
+			if (frappe.perm.has_perm("Account", 0, 'read')) {
+				frm.add_custom_button(__('Chart of Accounts'), function() {
+					frappe.set_route('Tree', 'Account', {'company': frm.doc.name});
+				}, __("View"));
+			}
 
-			frm.add_custom_button(__('Sales Tax Template'), function() {
-				frappe.set_route('List', 'Sales Taxes and Charges Template', {'company': frm.doc.name});
-			}, __("View"));
+			if (frappe.perm.has_perm("Sales Taxes and Charges Template", 0, 'read')) {
+				frm.add_custom_button(__('Sales Tax Template'), function() {
+					frappe.set_route('List', 'Sales Taxes and Charges Template', {'company': frm.doc.name});
+				}, __("View"));
+			}
 
-			frm.add_custom_button(__('Purchase Tax Template'), function() {
-				frappe.set_route('List', 'Purchase Taxes and Charges Template', {'company': frm.doc.name});
-			}, __("View"));
+			if (frappe.perm.has_perm("Purchase Taxes and Charges Template", 0, 'read')) {
+				frm.add_custom_button(__('Purchase Tax Template'), function() {
+					frappe.set_route('List', 'Purchase Taxes and Charges Template', {'company': frm.doc.name});
+				}, __("View"));
+			}
 
-			frm.add_custom_button(__('Default Tax Template'), function() {
-				frm.trigger("make_default_tax_template");
-			}, __('Create'));
+			if (frm.has_perm('write')) {
+				frm.add_custom_button(__('Default Tax Template'), function() {
+					frm.trigger("make_default_tax_template");
+				}, __('Create'));
+			}
 		}
 
 		erpnext.company.set_chart_of_accounts_options(frm.doc);
diff --git a/erpnext/setup/doctype/company/delete_company_transactions.py b/erpnext/setup/doctype/company/delete_company_transactions.py
index c94831e..566f20c 100644
--- a/erpnext/setup/doctype/company/delete_company_transactions.py
+++ b/erpnext/setup/doctype/company/delete_company_transactions.py
@@ -27,7 +27,8 @@
 		if doctype not in ("Account", "Cost Center", "Warehouse", "Budget",
 			"Party Account", "Employee", "Sales Taxes and Charges Template",
 			"Purchase Taxes and Charges Template", "POS Profile", "BOM",
-			"Company", "Bank Account"):
+			"Company", "Bank Account", "Item Tax Template", "Mode Of Payment",
+			"Item Default"):
 				delete_for_doctype(doctype, company_name)
 
 	# reset company values
diff --git a/erpnext/setup/doctype/email_digest/email_digest.py b/erpnext/setup/doctype/email_digest/email_digest.py
index b30bd78..cbb4c7c 100644
--- a/erpnext/setup/doctype/email_digest/email_digest.py
+++ b/erpnext/setup/doctype/email_digest/email_digest.py
@@ -48,12 +48,8 @@
 		recipients = list(filter(lambda r: r in valid_users,
 			self.recipient_list.split("\n")))
 
-		original_user = frappe.session.user
-
 		if recipients:
 			for user_id in recipients:
-				frappe.set_user(user_id)
-				frappe.set_user_lang(user_id)
 				msg_for_this_recipient = self.get_msg_html()
 				if msg_for_this_recipient:
 					frappe.sendmail(
@@ -64,9 +60,6 @@
 						reference_name = self.name,
 						unsubscribe_message = _("Unsubscribe from this Email Digest"))
 
-		frappe.set_user(original_user)
-		frappe.set_user_lang(original_user)
-
 	def get_msg_html(self):
 		"""Build email digest content"""
 		frappe.flags.ignore_account_permission = True
diff --git a/erpnext/setup/doctype/sales_person/sales_person.js b/erpnext/setup/doctype/sales_person/sales_person.js
index 8f7593d..b71a92f 100644
--- a/erpnext/setup/doctype/sales_person/sales_person.js
+++ b/erpnext/setup/doctype/sales_person/sales_person.js
@@ -5,8 +5,7 @@
 	refresh: function(frm) {
 		if(frm.doc.__onload && frm.doc.__onload.dashboard_info) {
 			var info = frm.doc.__onload.dashboard_info;
-			frm.dashboard.add_indicator(__('Total Contribution Amount: {0}',
-				[format_currency(info.allocated_amount, info.currency)]), 'blue');
+			frm.dashboard.add_indicator(__('Total Contribution Amount: {0}', [format_currency(info.allocated_amount, info.currency)]), 'blue');
 		}
 	},
 
diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.js b/erpnext/stock/doctype/delivery_note/delivery_note.js
index 19d0bec..251a26a 100644
--- a/erpnext/stock/doctype/delivery_note/delivery_note.js
+++ b/erpnext/stock/doctype/delivery_note/delivery_note.js
@@ -151,7 +151,7 @@
 								project: me.frm.doc.project || undefined,
 							}
 						})
-					}, __("Get items from"));
+					}, __("Get Items From"));
 			}
 		}
 
diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.json b/erpnext/stock/doctype/delivery_note/delivery_note.json
index ea385c8..7393c8a 100644
--- a/erpnext/stock/doctype/delivery_note/delivery_note.json
+++ b/erpnext/stock/doctype/delivery_note/delivery_note.json
@@ -1,5 +1,6 @@
 {
  "actions": [],
+ "allow_auto_repeat": 1,
  "allow_import": 1,
  "autoname": "naming_series:",
  "creation": "2013-05-24 19:29:09",
@@ -413,7 +414,8 @@
   {
    "fieldname": "company_address_display",
    "fieldtype": "Small Text",
-   "label": "Company Address"
+   "label": "Company Address",
+   "read_only": 1
   },
   {
    "collapsible": 1,
@@ -1255,7 +1257,7 @@
  "idx": 146,
  "is_submittable": 1,
  "links": [],
- "modified": "2020-08-03 23:18:47.739997",
+ "modified": "2020-11-11 14:57:16.388139",
  "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 0168613..9566af7 100644
--- a/erpnext/stock/doctype/delivery_note/test_delivery_note.py
+++ b/erpnext/stock/doctype/delivery_note/test_delivery_note.py
@@ -442,9 +442,15 @@
 		self.assertEqual(dn.status, "To Bill")
 		self.assertEqual(dn.per_billed, 0)
 
+		# Testing if Customer's Purchase Order No was rightly copied
+		self.assertEqual(dn.po_no, so.po_no)
+
 		si = make_sales_invoice(dn.name)
 		si.submit()
 
+		# Testing if Customer's Purchase Order No was rightly copied
+		self.assertEqual(dn.po_no, si.po_no)
+
 		dn.load_from_db()
 		self.assertEqual(dn.get("items")[0].billed_amt, 200)
 		self.assertEqual(dn.per_billed, 100)
@@ -461,16 +467,25 @@
 		si.insert()
 		si.submit()
 
+		# Testing if Customer's Purchase Order No was rightly copied
+		self.assertEqual(so.po_no, si.po_no)
+
 		frappe.db.set_value("Stock Settings", None, "allow_negative_stock", 1)
 
 		dn1 = make_delivery_note(so.name)
 		dn1.get("items")[0].qty = 2
 		dn1.submit()
 
+		# Testing if Customer's Purchase Order No was rightly copied
+		self.assertEqual(so.po_no, dn1.po_no)
+
 		dn2 = make_delivery_note(so.name)
 		dn2.get("items")[0].qty = 3
 		dn2.submit()
 
+		# Testing if Customer's Purchase Order No was rightly copied
+		self.assertEqual(so.po_no, dn2.po_no)
+
 		dn1.load_from_db()
 		self.assertEqual(dn1.get("items")[0].billed_amt, 200)
 		self.assertEqual(dn1.per_billed, 100)
@@ -492,9 +507,15 @@
 		dn1.get("items")[0].qty = 2
 		dn1.submit()
 
+		# Testing if Customer's Purchase Order No was rightly copied
+		self.assertEqual(dn1.po_no, so.po_no)
+
 		si1 = make_sales_invoice(dn1.name)
 		si1.submit()
 
+		# Testing if Customer's Purchase Order No was rightly copied
+		self.assertEqual(dn1.po_no, si1.po_no)
+
 		dn1.load_from_db()
 		self.assertEqual(dn1.per_billed, 100)
 
@@ -502,10 +523,16 @@
 		si2.get("items")[0].qty = 4
 		si2.submit()
 
+		# Testing if Customer's Purchase Order No was rightly copied
+		self.assertEqual(si2.po_no, so.po_no)
+
 		dn2 = make_delivery_note(so.name)
 		dn2.get("items")[0].qty = 5
 		dn2.submit()
 
+		# Testing if Customer's Purchase Order No was rightly copied
+		self.assertEqual(dn2.po_no, so.po_no)
+
 		dn1.load_from_db()
 		self.assertEqual(dn1.get("items")[0].billed_amt, 200)
 		self.assertEqual(dn1.per_billed, 100)
@@ -525,9 +552,15 @@
 		si = make_sales_invoice(so.name)
 		si.submit()
 
+		# Testing if Customer's Purchase Order No was rightly copied
+		self.assertEqual(so.po_no, si.po_no)
+
 		dn = make_delivery_note(si.name)
 		dn.submit()
 
+		# Testing if Customer's Purchase Order No was rightly copied
+		self.assertEqual(dn.po_no, si.po_no)
+
 		self.assertEqual(dn.get("items")[0].billed_amt, 1000)
 		self.assertEqual(dn.per_billed, 100)
 		self.assertEqual(dn.status, "Completed")
diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py
index 3b62c38..be845d9 100644
--- a/erpnext/stock/doctype/item/item.py
+++ b/erpnext/stock/doctype/item/item.py
@@ -977,15 +977,20 @@
 		# For "Is Stock Item", following doctypes is important
 		# because reserved_qty, ordered_qty and requested_qty updated from these doctypes
 		if field == "is_stock_item":
-			linked_doctypes += ["Sales Order Item", "Purchase Order Item", "Material Request Item"]
+			linked_doctypes += ["Sales Order Item", "Purchase Order Item", "Material Request Item", "Product Bundle"]
 
 		for doctype in linked_doctypes:
+			filters={"item_code": self.name, "docstatus": 1}
+
+			if doctype == "Product Bundle":
+				filters={"new_item_code": self.name}
+
 			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}):
+			elif frappe.db.get_value(doctype, filters):
 				return True
 
 	def validate_auto_reorder_enabled_in_stock_settings(self):
diff --git a/erpnext/stock/doctype/item_price/item_price.py b/erpnext/stock/doctype/item_price/item_price.py
index 51b47c5..bed5ea9 100644
--- a/erpnext/stock/doctype/item_price/item_price.py
+++ b/erpnext/stock/doctype/item_price/item_price.py
@@ -4,14 +4,13 @@
 from __future__ import unicode_literals
 import frappe
 from frappe import _
-
-
-class ItemPriceDuplicateItem(frappe.ValidationError): pass
-
-
 from frappe.model.document import Document
 
 
+class ItemPriceDuplicateItem(frappe.ValidationError):
+	pass
+
+
 class ItemPrice(Document):
 
 	def validate(self):
@@ -23,7 +22,7 @@
 
 	def validate_item(self):
 		if not frappe.db.exists("Item", self.item_code):
-			frappe.throw(_("Item {0} not found").format(self.item_code))
+			frappe.throw(_("Item {0} not found.").format(self.item_code))
 
 	def validate_dates(self):
 		if self.valid_from and self.valid_upto:
@@ -38,40 +37,45 @@
 
 			if not price_list_details:
 				link = frappe.utils.get_link_to_form('Price List', self.price_list)
-				frappe.throw("The price list {0} does not exists or disabled".
-					format(link))
+				frappe.throw("The price list {0} does not exist or is disabled".format(link))
 
 			self.buying, self.selling, self.currency = price_list_details
 
 	def update_item_details(self):
 		if self.item_code:
-			self.item_name, self.item_description = frappe.db.get_value("Item",
-				self.item_code,["item_name", "description"])
+			self.item_name, self.item_description = frappe.db.get_value("Item", self.item_code,["item_name", "description"])
 
 	def check_duplicates(self):
-		conditions = "where item_code=%(item_code)s and price_list=%(price_list)s and name != %(name)s"
-		condition_data_dict = dict(item_code=self.item_code, price_list=self.price_list, name=self.name)
+		conditions = """where item_code = %(item_code)s and price_list = %(price_list)s and name != %(name)s"""
 
-		for field in ['uom', 'valid_from',
-			'valid_upto', 'packing_unit', 'customer', 'supplier']:
+		for field in [
+			"uom",
+			"valid_from",
+			"valid_upto",
+			"packing_unit",
+			"customer",
+			"supplier",]:
 			if self.get(field):
-				conditions += " and {0} = %({1})s".format(field, field)
-				condition_data_dict[field] = self.get(field)
+				conditions += " and {0} = %({0})s ".format(field)
+			else:
+				conditions += "and (isnull({0}) or {0} = '')".format(field)
 
 		price_list_rate = frappe.db.sql("""
-			SELECT price_list_rate
-			FROM `tabItem Price`
-			  {conditions} """.format(conditions=conditions), condition_data_dict)
+				select price_list_rate
+				from `tabItem Price`
+				{conditions}
+			""".format(conditions=conditions),
+			self.as_dict(),)
 
-		if price_list_rate :
-			frappe.throw(_("Item Price appears multiple times based on Price List, Supplier/Customer, Currency, Item, UOM, Qty and Dates."), ItemPriceDuplicateItem)
+		if price_list_rate:
+			frappe.throw(_("Item Price appears multiple times based on Price List, Supplier/Customer, Currency, Item, UOM, Qty, and Dates."), ItemPriceDuplicateItem,)
 
 	def before_save(self):
 		if self.selling:
 			self.reference = self.customer
 		if self.buying:
 			self.reference = self.supplier
-		
+
 		if self.selling and not self.buying:
 			# if only selling then remove supplier
 			self.supplier = None
diff --git a/erpnext/stock/doctype/item_price/test_item_price.py b/erpnext/stock/doctype/item_price/test_item_price.py
index 702acc3..f3d406e 100644
--- a/erpnext/stock/doctype/item_price/test_item_price.py
+++ b/erpnext/stock/doctype/item_price/test_item_price.py
@@ -138,4 +138,23 @@
 		# Valid price list must already exist
 		self.assertRaises(frappe.ValidationError, doc.save)
 
+	def test_empty_duplicate_validation(self):
+		# Check if none/empty values are not compared during insert validation
+		doc = frappe.copy_doc(test_records[2])
+		doc.customer = None
+		doc.price_list_rate = 21
+		doc.insert()
+
+		args = {
+			"price_list": doc.price_list,
+			"uom": "_Test UOM",
+			"transaction_date": '2017-04-18',
+			"qty": 7
+		}
+
+		price = get_price_list_rate_for(args, doc.item_code)
+		frappe.db.rollback()
+
+		self.assertEqual(price, 21)
+
 test_records = frappe.get_test_records('Item Price')
diff --git a/erpnext/stock/doctype/item_quality_inspection_parameter/item_quality_inspection_parameter.json b/erpnext/stock/doctype/item_quality_inspection_parameter/item_quality_inspection_parameter.json
index f1e1fd3..888bc2d 100644
--- a/erpnext/stock/doctype/item_quality_inspection_parameter/item_quality_inspection_parameter.json
+++ b/erpnext/stock/doctype/item_quality_inspection_parameter/item_quality_inspection_parameter.json
@@ -1,88 +1,57 @@
 {
- "allow_copy": 0, 
- "allow_import": 0, 
- "allow_rename": 0, 
- "autoname": "hash", 
- "beta": 0, 
- "creation": "2013-02-22 01:28:01", 
- "custom": 0, 
- "docstatus": 0, 
- "doctype": "DocType", 
- "editable_grid": 1, 
+ "actions": [],
+ "autoname": "hash",
+ "creation": "2013-02-22 01:28:01",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "specification",
+  "value",
+  "column_break_3",
+  "acceptance_formula"
+ ],
  "fields": [
   {
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "fieldname": "specification", 
-   "fieldtype": "Data", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_list_view": 1, 
-   "label": "Parameter", 
-   "length": 0, 
-   "no_copy": 0, 
-   "oldfieldname": "specification", 
-   "oldfieldtype": "Data", 
-   "permlevel": 0, 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "print_width": "200px", 
-   "read_only": 0, 
-   "report_hide": 0, 
-   "reqd": 1, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "unique": 0, 
+   "fieldname": "specification",
+   "fieldtype": "Data",
+   "in_list_view": 1,
+   "label": "Parameter",
+   "oldfieldname": "specification",
+   "oldfieldtype": "Data",
+   "print_width": "200px",
+   "reqd": 1,
    "width": "200px"
-  }, 
+  },
   {
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "fieldname": "value", 
-   "fieldtype": "Data", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_list_view": 1, 
-   "label": "Acceptance Criteria", 
-   "length": 0, 
-   "no_copy": 0, 
-   "oldfieldname": "value", 
-   "oldfieldtype": "Data", 
-   "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": "value",
+   "fieldtype": "Data",
+   "in_list_view": 1,
+   "label": "Acceptance Criteria",
+   "oldfieldname": "value",
+   "oldfieldtype": "Data"
+  },
+  {
+   "fieldname": "column_break_3",
+   "fieldtype": "Column Break"
+  },
+  {
+   "description": "Simple Python formula based on numeric Readings.<br> Example 1: <b>reading_1 &gt; 0.2 and reading_1 &lt; 0.5</b><br>\nExample 2: <b>(reading_1 + reading_2) / 2 &lt; 10</b>",
+   "fieldname": "acceptance_formula",
+   "fieldtype": "Code",
+   "in_list_view": 1,
+   "label": "Acceptance Criteria Formula"
   }
- ], 
- "hide_heading": 0, 
- "hide_toolbar": 0, 
- "idx": 1, 
- "image_view": 0, 
- "in_create": 0, 
-
- "is_submittable": 0, 
- "issingle": 0, 
- "istable": 1, 
- "max_attachments": 0, 
- "modified": "2016-07-11 03:28:01.074316", 
- "modified_by": "Administrator", 
- "module": "Stock", 
- "name": "Item Quality Inspection Parameter", 
- "owner": "Administrator", 
- "permissions": [], 
- "quick_entry": 0, 
- "read_only": 0, 
- "read_only_onload": 0, 
- "track_seen": 0
+ ],
+ "idx": 1,
+ "istable": 1,
+ "links": [],
+ "modified": "2020-11-16 16:33:42.421842",
+ "modified_by": "Administrator",
+ "module": "Stock",
+ "name": "Item Quality Inspection Parameter",
+ "owner": "Administrator",
+ "permissions": [],
+ "sort_field": "modified",
+ "sort_order": "DESC"
 }
\ No newline at end of file
diff --git a/erpnext/stock/doctype/material_request/material_request.js b/erpnext/stock/doctype/material_request/material_request.js
index 8c47098..01edd99 100644
--- a/erpnext/stock/doctype/material_request/material_request.js
+++ b/erpnext/stock/doctype/material_request/material_request.js
@@ -90,7 +90,7 @@
 	make_custom_buttons: function(frm) {
 		if (frm.doc.docstatus==0) {
 			frm.add_custom_button(__("Bill of Materials"),
-				() => frm.events.get_items_from_bom(frm), __("Get items from"));
+				() => frm.events.get_items_from_bom(frm), __("Get Items From"));
 		}
 
 		if (frm.doc.docstatus == 1 && frm.doc.status != 'Stopped') {
@@ -147,7 +147,7 @@
 
 		if (frm.doc.docstatus===0) {
 			frm.add_custom_button(__('Sales Order'), () => frm.events.get_items_from_sales_order(frm),
-				__("Get items from"));
+				__("Get Items From"));
 		}
 
 		if (frm.doc.docstatus == 1 && frm.doc.status == 'Stopped') {
@@ -173,7 +173,8 @@
 			source_doctype: "Sales Order",
 			target: frm,
 			setters: {
-				customer: frm.doc.customer || undefined
+				customer: frm.doc.customer || undefined,
+				delivery_date: undefined,
 			},
 			get_query_filters: {
 				docstatus: 1,
@@ -280,8 +281,7 @@
 				fieldname:'default_supplier',
 				fieldtype: 'Link',
 				options: 'Supplier',
-				description: __('Select a Supplier from the Default Suppliers of the items below. \
-					On selection, a Purchase Order will be made against items belonging to the selected Supplier only.'),
+				description: __('Select a Supplier from the Default Suppliers of the items below. On selection, a Purchase Order will be made against items belonging to the selected Supplier only.'),
 				get_query: () => {
 					return{
 						query: "erpnext.stock.doctype.material_request.material_request.get_default_supplier_query",
diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js
index c504e23..bc1d81d 100644
--- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js
+++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js
@@ -128,6 +128,7 @@
 							target: me.frm,
 							setters: {
 								supplier: me.frm.doc.supplier,
+								schedule_date: undefined
 							},
 							get_query_filters: {
 								docstatus: 1,
@@ -136,7 +137,7 @@
 								company: me.frm.doc.company
 							}
 						})
-					}, __("Get items from"));
+					}, __("Get Items From"));
 			}
 
 			if(this.frm.doc.docstatus == 1 && this.frm.doc.status!="Closed") {
diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json
index ce54fc8..13c8ceb 100755
--- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json
+++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json
@@ -1,5 +1,6 @@
 {
  "actions": [],
+ "allow_auto_repeat": 1,
  "allow_import": 1,
  "autoname": "naming_series:",
  "creation": "2013-05-21 16:16:39",
@@ -1109,7 +1110,7 @@
  "idx": 261,
  "is_submittable": 1,
  "links": [],
- "modified": "2020-08-03 23:20:26.381024",
+ "modified": "2020-10-30 14:00:08.347534",
  "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 faa9dd9..2cc4679 100644
--- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
+++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
@@ -533,6 +533,8 @@
 @frappe.whitelist()
 def make_purchase_invoice(source_name, target_doc=None):
 	from frappe.model.mapper import get_mapped_doc
+	from erpnext.accounts.party import get_payment_terms_template
+
 	doc = frappe.get_doc('Purchase Receipt', source_name)
 	returned_qty_map = get_returned_qty_map(source_name)
 	invoiced_qty_map = get_invoiced_qty_map(source_name)
@@ -543,6 +545,7 @@
 
 		doc = frappe.get_doc(target)
 		doc.ignore_pricing_rule = 1
+		doc.payment_terms_template = get_payment_terms_template(source.supplier, "Supplier", source.company)
 		doc.run_method("onload")
 		doc.run_method("set_missing_values")
 		doc.run_method("calculate_taxes_and_totals")
@@ -569,7 +572,8 @@
 			"doctype": "Purchase Invoice",
 			"field_map": {
 				"supplier_warehouse":"supplier_warehouse",
-				"is_return": "is_return"
+				"is_return": "is_return",
+				"bill_date": "bill_date"
 			},
 			"validation": {
 				"docstatus": ["=", 1],
diff --git a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py
index a1e01bf..253edb0 100644
--- a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py
+++ b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py
@@ -42,6 +42,30 @@
 		frappe.db.set_value('UOM', '_Test UOM', 'must_be_whole_number', 1)
 
 	def test_make_purchase_invoice(self):
+		if not frappe.db.exists('Payment Terms Template', '_Test Payment Terms Template For Purchase Invoice'):
+			frappe.get_doc({
+				'doctype': 'Payment Terms Template',
+				'template_name': '_Test Payment Terms Template For Purchase Invoice',
+				'allocate_payment_based_on_payment_terms': 1,
+				'terms': [
+					{
+						'doctype': 'Payment Terms Template Detail',
+						'invoice_portion': 50.00,
+						'credit_days_based_on': 'Day(s) after invoice date',
+						'credit_days': 00
+					},
+					{
+						'doctype': 'Payment Terms Template Detail',
+						'invoice_portion': 50.00,
+						'credit_days_based_on': 'Day(s) after invoice date',
+						'credit_days': 30
+					}]
+			}).insert()
+
+		template = frappe.db.get_value('Payment Terms Template', '_Test Payment Terms Template For Purchase Invoice')
+		old_template_in_supplier = frappe.db.get_value("Supplier", "_Test Supplier", "payment_terms")
+		frappe.db.set_value("Supplier", "_Test Supplier", "payment_terms", template)
+
 		pr = make_purchase_receipt(do_not_save=True)
 		self.assertRaises(frappe.ValidationError, make_purchase_invoice, pr.name)
 		pr.submit()
@@ -51,10 +75,23 @@
 		self.assertEqual(pi.doctype, "Purchase Invoice")
 		self.assertEqual(len(pi.get("items")), len(pr.get("items")))
 
-		# modify rate
+		# test maintaining same rate throughout purchade cycle
 		pi.get("items")[0].rate = 200
 		self.assertRaises(frappe.ValidationError, frappe.get_doc(pi).submit)
 
+		# test if payment terms are fetched and set in PI
+		self.assertEqual(pi.payment_terms_template, template)
+		self.assertEqual(pi.payment_schedule[0].payment_amount, flt(pi.grand_total)/2)
+		self.assertEqual(pi.payment_schedule[0].invoice_portion, 50)
+		self.assertEqual(pi.payment_schedule[1].payment_amount, flt(pi.grand_total)/2)
+		self.assertEqual(pi.payment_schedule[1].invoice_portion, 50)
+
+		# teardown
+		pi.delete() # draft PI
+		pr.cancel()
+		frappe.db.set_value("Supplier", "_Test Supplier", "payment_terms", old_template_in_supplier)
+		frappe.get_doc('Payment Terms Template', '_Test Payment Terms Template For Purchase Invoice').delete()
+
 	def test_purchase_receipt_no_gl_entry(self):
 		company = frappe.db.get_value('Warehouse', '_Test Warehouse - _TC', 'company')
 
diff --git a/erpnext/stock/doctype/quality_inspection/quality_inspection.js b/erpnext/stock/doctype/quality_inspection/quality_inspection.js
index 22f29e0..376848a 100644
--- a/erpnext/stock/doctype/quality_inspection/quality_inspection.js
+++ b/erpnext/stock/doctype/quality_inspection/quality_inspection.js
@@ -31,17 +31,27 @@
 
 // item code based on GRN/DN
 cur_frm.fields_dict['item_code'].get_query = function(doc, cdt, cdn) {
-	const doctype = (doc.reference_type == "Stock Entry") ?
-		"Stock Entry Detail" : doc.reference_type + " Item";
+	let doctype = doc.reference_type;
+
+	if (doc.reference_type !== "Job Card") {
+		doctype = (doc.reference_type == "Stock Entry") ?
+			"Stock Entry Detail" : doc.reference_type + " Item";
+	}
 
 	if (doc.reference_type && doc.reference_name) {
+		let filters = {
+			"from": doctype,
+			"inspection_type": doc.inspection_type
+		};
+
+		if (doc.reference_type == doctype)
+			filters["reference_name"] = doc.reference_name;
+		else
+			filters["parent"] = doc.reference_name;
+
 		return {
 			query: "erpnext.stock.doctype.quality_inspection.quality_inspection.item_query",
-			filters: {
-				"from": doctype,
-				"parent": doc.reference_name,
-				"inspection_type": doc.inspection_type
-			}
+			filters: filters
 		};
 	}
 },
diff --git a/erpnext/stock/doctype/quality_inspection/quality_inspection.json b/erpnext/stock/doctype/quality_inspection/quality_inspection.json
index dd95075..f6d7619 100644
--- a/erpnext/stock/doctype/quality_inspection/quality_inspection.json
+++ b/erpnext/stock/doctype/quality_inspection/quality_inspection.json
@@ -73,7 +73,7 @@
    "fieldname": "reference_type",
    "fieldtype": "Select",
    "label": "Reference Type",
-   "options": "\nPurchase Receipt\nPurchase Invoice\nDelivery Note\nSales Invoice\nStock Entry",
+   "options": "\nPurchase Receipt\nPurchase Invoice\nDelivery Note\nSales Invoice\nStock Entry\nJob Card",
    "reqd": 1
   },
   {
@@ -236,7 +236,7 @@
  "index_web_pages_for_search": 1,
  "is_submittable": 1,
  "links": [],
- "modified": "2020-10-21 13:03:11.938072",
+ "modified": "2020-11-19 17:06:05.409963",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Quality Inspection",
diff --git a/erpnext/stock/doctype/quality_inspection/quality_inspection.py b/erpnext/stock/doctype/quality_inspection/quality_inspection.py
index c3bb514..ae4eb9b 100644
--- a/erpnext/stock/doctype/quality_inspection/quality_inspection.py
+++ b/erpnext/stock/doctype/quality_inspection/quality_inspection.py
@@ -4,15 +4,20 @@
 from __future__ import unicode_literals
 import frappe
 from frappe.model.document import Document
+from frappe.model.mapper import get_mapped_doc
+from frappe import _
+from frappe.utils import flt
 from erpnext.stock.doctype.quality_inspection_template.quality_inspection_template \
 	import get_template_details
-from frappe.model.mapper import get_mapped_doc
 
 class QualityInspection(Document):
 	def validate(self):
 		if not self.readings and self.item_code:
 			self.get_item_specification_details()
 
+		if self.readings:
+			self.set_status_based_on_acceptance_formula()
+
 	def get_item_specification_details(self):
 		if not self.quality_inspection_template:
 			self.quality_inspection_template = frappe.db.get_value('Item',
@@ -26,6 +31,7 @@
 			child = self.append('readings', {})
 			child.specification = d.specification
 			child.value = d.value
+			child.acceptance_formula = d.acceptance_formula
 			child.status = "Accepted"
 
 	def get_quality_inspection_template(self):
@@ -47,16 +53,51 @@
 
 	def update_qc_reference(self):
 		quality_inspection = self.name if self.docstatus == 1 else ""
-		doctype = self.reference_type + ' Item'
-		if self.reference_type == 'Stock Entry':
-			doctype = 'Stock Entry Detail'
 
-		if self.reference_type and self.reference_name:
-			frappe.db.sql("""update `tab{child_doc}` t1, `tab{parent_doc}` t2
-				set t1.quality_inspection = %s, t2.modified = %s
-				where t1.parent = %s and t1.item_code = %s and t1.parent = t2.name"""
-				.format(parent_doc=self.reference_type, child_doc=doctype),
-				(quality_inspection, self.modified, self.reference_name, self.item_code))
+		if self.reference_type == 'Job Card':
+			if self.reference_name:
+				frappe.db.sql("""
+					UPDATE `tab{doctype}`
+					SET quality_inspection = %s, modified = %s
+					WHERE name = %s and production_item = %s
+				""".format(doctype=self.reference_type),
+					(quality_inspection, self.modified, self.reference_name, self.item_code))
+
+		else:
+			doctype = self.reference_type + ' Item'
+			if self.reference_type == 'Stock Entry':
+				doctype = 'Stock Entry Detail'
+
+			if self.reference_type and self.reference_name:
+				frappe.db.sql("""
+					UPDATE `tab{child_doc}` t1, `tab{parent_doc}` t2
+					SET t1.quality_inspection = %s, t2.modified = %s
+					WHERE t1.parent = %s and t1.item_code = %s and t1.parent = t2.name
+				""".format(parent_doc=self.reference_type, child_doc=doctype),
+					(quality_inspection, self.modified, self.reference_name, self.item_code))
+
+	def set_status_based_on_acceptance_formula(self):
+		for reading in self.readings:
+			if not reading.acceptance_formula: continue
+
+			condition = reading.acceptance_formula
+			data = {}
+			for i in range(1, 11):
+				field = "reading_" + str(i)
+				data[field] = flt(reading.get(field)) or 0
+
+			try:
+				result = frappe.safe_eval(condition, None, data)
+				reading.status = "Accepted" if result else "Rejected"
+			except SyntaxError:
+				frappe.throw(_("Row #{0}: Acceptance Criteria Formula is incorrect.").format(reading.idx),
+					title=_("Invalid Formula"))
+			except NameError as e:
+				field = frappe.bold(e.args[0].split()[1])
+				frappe.throw(_("Row #{0}: {1} is not a valid reading field. Please refer to the field description.")
+					.format(reading.idx, field),
+					title=_("Invalid Formula"))
+
 
 @frappe.whitelist()
 @frappe.validate_and_sanitize_search_inputs
@@ -66,27 +107,44 @@
 		mcond = get_match_cond(filters["from"])
 		cond, qi_condition = "", "and (quality_inspection is null or quality_inspection = '')"
 
-		if filters.get('from') in ['Purchase Invoice Item', 'Purchase Receipt Item']\
-				and filters.get("inspection_type") != "In Process":
-			cond = """and item_code in (select name from `tabItem` where
-				inspection_required_before_purchase = 1)"""
-		elif filters.get('from') in ['Sales Invoice Item', 'Delivery Note Item']\
-				and filters.get("inspection_type") != "In Process":
-			cond = """and item_code in (select name from `tabItem` where
-				inspection_required_before_delivery = 1)"""
-		elif filters.get('from') == 'Stock Entry Detail':
-			cond = """and s_warehouse is null"""
+		if filters.get("parent"):
+			if filters.get('from') in ['Purchase Invoice Item', 'Purchase Receipt Item']\
+					and filters.get("inspection_type") != "In Process":
+				cond = """and item_code in (select name from `tabItem` where
+					inspection_required_before_purchase = 1)"""
+			elif filters.get('from') in ['Sales Invoice Item', 'Delivery Note Item']\
+					and filters.get("inspection_type") != "In Process":
+				cond = """and item_code in (select name from `tabItem` where
+					inspection_required_before_delivery = 1)"""
+			elif filters.get('from') == 'Stock Entry Detail':
+				cond = """and s_warehouse is null"""
 
-		if filters.get('from') in ['Supplier Quotation Item']:
-			qi_condition = ""
+			if filters.get('from') in ['Supplier Quotation Item']:
+				qi_condition = ""
 
-		return frappe.db.sql(""" select item_code from `tab{doc}`
-			where parent=%(parent)s and docstatus < 2 and item_code like %(txt)s
-			{qi_condition} {cond} {mcond}
-			order by item_code limit {start}, {page_len}""".format(doc=filters.get('from'),
-			parent=filters.get('parent'), cond = cond, mcond = mcond, start = start,
-			page_len = page_len, qi_condition = qi_condition),
-			{'parent': filters.get('parent'), 'txt': "%%%s%%" % txt})
+			return frappe.db.sql("""
+					SELECT item_code
+					FROM `tab{doc}`
+					WHERE parent=%(parent)s and docstatus < 2 and item_code like %(txt)s
+					{qi_condition} {cond} {mcond}
+					ORDER BY item_code limit {start}, {page_len}
+				""".format(doc=filters.get('from'),
+					cond = cond, mcond = mcond, start = start,
+					page_len = page_len, qi_condition = qi_condition),
+					{'parent': filters.get('parent'), 'txt': "%%%s%%" % txt})
+
+		elif filters.get("reference_name"):
+			return frappe.db.sql("""
+					SELECT production_item
+					FROM `tab{doc}`
+					WHERE name = %(reference_name)s and docstatus < 2 and production_item like %(txt)s
+					{qi_condition} {cond} {mcond}
+					ORDER BY production_item
+					LIMIT {start}, {page_len}
+				""".format(doc=filters.get("from"),
+					cond = cond, mcond = mcond, start = start,
+					page_len = page_len, qi_condition = qi_condition),
+					{'reference_name': filters.get('reference_name'), 'txt': "%%%s%%" % txt})
 
 @frappe.whitelist()
 @frappe.validate_and_sanitize_search_inputs
diff --git a/erpnext/stock/doctype/quality_inspection/test_quality_inspection.py b/erpnext/stock/doctype/quality_inspection/test_quality_inspection.py
index bb535c1..2c40009 100644
--- a/erpnext/stock/doctype/quality_inspection/test_quality_inspection.py
+++ b/erpnext/stock/doctype/quality_inspection/test_quality_inspection.py
@@ -7,6 +7,7 @@
 from frappe.utils import nowdate
 from erpnext.stock.doctype.item.test_item import create_item
 from erpnext.stock.doctype.delivery_note.test_delivery_note import create_delivery_note
+from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry
 from erpnext.controllers.stock_controller import QualityInspectionRejectedError, QualityInspectionRequiredError, QualityInspectionNotSubmittedError
 
 # test_records = frappe.get_test_records('Quality Inspection')
@@ -17,10 +18,12 @@
 		frappe.db.set_value("Item", "_Test Item with QA", "inspection_required_before_delivery", 1)
 
 	def test_qa_for_delivery(self):
+		make_stock_entry(item_code="_Test Item with QA", target="_Test Warehouse - _TC", qty=1, basic_rate=100)
 		dn = create_delivery_note(item_code="_Test Item with QA", do_not_submit=True)
+
 		self.assertRaises(QualityInspectionRequiredError, dn.submit)
 
-		qa = create_quality_inspection(reference_type="Delivery Note", reference_name=dn.name, status="Rejected", submit=True)
+		qa = create_quality_inspection(reference_type="Delivery Note", reference_name=dn.name, status="Rejected")
 		dn.reload()
 		self.assertRaises(QualityInspectionRejectedError, dn.submit)
 
@@ -28,12 +31,51 @@
 		dn.reload()
 		dn.submit()
 
+		qa.cancel()
+		dn.reload()
+		dn.cancel()
+
 	def test_qa_not_submit(self):
 		dn = create_delivery_note(item_code="_Test Item with QA", do_not_submit=True)
-		qa = create_quality_inspection(reference_type="Delivery Note", reference_name=dn.name, submit = False)
+		qa = create_quality_inspection(reference_type="Delivery Note", reference_name=dn.name, do_not_submit=True)
 		dn.items[0].quality_inspection = qa.name
 		self.assertRaises(QualityInspectionNotSubmittedError, dn.submit)
 
+		qa.delete()
+		dn.delete()
+
+	def test_formula_based_qi_readings(self):
+		dn = create_delivery_note(item_code="_Test Item with QA", do_not_submit=True)
+		readings = [{
+			"specification": "Iron Content",
+			"acceptance_formula": "reading_1 > 0.35 and reading_1 < 0.50",
+			"reading_1": 0.4
+		},
+		{
+			"specification": "Calcium Content",
+			"acceptance_formula": "reading_1 > 0.20 and reading_1 < 0.50",
+			"reading_1": 0.7
+		},
+		{
+			"specification": "Mg Content",
+			"acceptance_formula": "(reading_1 + reading_2 + reading_3) / 3 < 0.9",
+			"reading_1": 0.5,
+			"reading_2": 0.7,
+			"reading_3": "random text" # check if random string input causes issues
+		}]
+
+		qa = create_quality_inspection(reference_type="Delivery Note", reference_name=dn.name,
+			readings=readings, do_not_save=True)
+		qa.save()
+
+		# status must be auto set as per formula
+		self.assertEqual(qa.readings[0].status, "Accepted")
+		self.assertEqual(qa.readings[1].status, "Rejected")
+		self.assertEqual(qa.readings[2].status, "Accepted")
+
+		qa.delete()
+		dn.delete()
+
 def create_quality_inspection(**args):
 	args = frappe._dict(args)
 	qa = frappe.new_doc("Quality Inspection")
@@ -44,12 +86,18 @@
 	qa.item_code = args.item_code or "_Test Item with QA"
 	qa.sample_size = 1
 	qa.inspected_by = frappe.session.user
-	qa.append("readings", {
-		"specification": "Size",
-		"status": args.status
-	})
-	qa.save()
-	if args.submit:
-		qa.submit()
+
+	readings = args.readings or {"specification": "Size", "status": args.status}
+
+	if isinstance(readings, list):
+		for entry in readings:
+			qa.append("readings", entry)
+	else:
+		qa.append("readings", readings)
+
+	if not args.do_not_save:
+		qa.save()
+		if not args.do_not_submit:
+			qa.submit()
 
 	return qa
diff --git a/erpnext/stock/doctype/quality_inspection_reading/quality_inspection_reading.json b/erpnext/stock/doctype/quality_inspection_reading/quality_inspection_reading.json
index f9f8a71..c1976dd 100644
--- a/erpnext/stock/doctype/quality_inspection_reading/quality_inspection_reading.json
+++ b/erpnext/stock/doctype/quality_inspection_reading/quality_inspection_reading.json
@@ -1,22 +1,29 @@
 {
+ "actions": [],
  "autoname": "hash",
  "creation": "2013-02-22 01:27:43",
  "doctype": "DocType",
  "editable_grid": 1,
+ "engine": "InnoDB",
  "field_order": [
   "specification",
   "value",
+  "status",
+  "column_break_4",
+  "acceptance_formula",
+  "section_break_3",
   "reading_1",
   "reading_2",
   "reading_3",
+  "column_break_10",
   "reading_4",
   "reading_5",
   "reading_6",
+  "column_break_14",
   "reading_7",
   "reading_8",
   "reading_9",
-  "reading_10",
-  "status"
+  "reading_10"
  ],
  "fields": [
   {
@@ -124,15 +131,40 @@
    "oldfieldname": "status",
    "oldfieldtype": "Select",
    "options": "Accepted\nRejected"
+  },
+  {
+   "fieldname": "section_break_3",
+   "fieldtype": "Section Break"
+  },
+  {
+   "fieldname": "column_break_4",
+   "fieldtype": "Column Break"
+  },
+  {
+   "description": "Simple Python formula based on numeric Readings.<br> Example 1: <b>reading_1 &gt; 0.2 and reading_1 &lt; 0.5</b><br>\nExample 2: <b>(reading_1 + reading_2) / 2 &lt; 10</b>",
+   "fieldname": "acceptance_formula",
+   "fieldtype": "Code",
+   "label": "Acceptance Criteria Formula"
+  },
+  {
+   "fieldname": "column_break_10",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "column_break_14",
+   "fieldtype": "Column Break"
   }
  ],
  "idx": 1,
  "istable": 1,
- "modified": "2019-07-11 18:48:12.667404",
+ "links": [],
+ "modified": "2020-11-16 16:34:29.947856",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Quality Inspection Reading",
  "owner": "Administrator",
  "permissions": [],
+ "sort_field": "modified",
+ "sort_order": "DESC",
  "track_changes": 1
 }
\ No newline at end of file
diff --git a/erpnext/stock/doctype/quality_inspection_template/quality_inspection_template.py b/erpnext/stock/doctype/quality_inspection_template/quality_inspection_template.py
index 0d9a903..e284846 100644
--- a/erpnext/stock/doctype/quality_inspection_template/quality_inspection_template.py
+++ b/erpnext/stock/doctype/quality_inspection_template/quality_inspection_template.py
@@ -12,5 +12,7 @@
 def get_template_details(template):
 	if not template: return []
 
-	return frappe.get_all('Item Quality Inspection Parameter', fields=["specification", "value"],
-		filters={'parenttype': 'Quality Inspection Template', 'parent': template}, order_by="idx")
\ No newline at end of file
+	return frappe.get_all('Item Quality Inspection Parameter',
+		fields=["specification", "value", "acceptance_formula"],
+		filters={'parenttype': 'Quality Inspection Template', 'parent': template},
+		order_by="idx")
\ No newline at end of file
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.js b/erpnext/stock/doctype/stock_entry/stock_entry.js
index 39fd029..9121758 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.js
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.js
@@ -225,7 +225,7 @@
 						docstatus: 1
 					}
 				})
-			}, __("Get items from"));
+			}, __("Get Items From"));
 
 			frm.add_custom_button(__('Material Request'), function() {
 				erpnext.utils.map_current_doc({
@@ -240,7 +240,7 @@
 						status: ["not in", ["Transferred", "Issued"]]
 					}
 				})
-			}, __("Get items from"));
+			}, __("Get Items From"));
 		}
 		if (frm.doc.docstatus===0 && frm.doc.purpose == "Material Issue") {
 			frm.add_custom_button(__('Expired Batches'), function() {
@@ -263,7 +263,7 @@
 						}
 					}
 				});
-			}, __("Get items from"));
+			}, __("Get Items From"));
 		}
 
 		frm.events.show_bom_custom_button(frm);
@@ -282,7 +282,7 @@
 	},
 
 	stock_entry_type: function(frm){
-		frm.remove_custom_button('Bill of Materials', "Get items from");
+		frm.remove_custom_button('Bill of Materials', "Get Items From");
 		frm.events.show_bom_custom_button(frm);
 		frm.trigger('add_to_transit');
 	},
@@ -425,9 +425,9 @@
 	show_bom_custom_button: function(frm){
 		if (frm.doc.docstatus === 0 &&
 			['Material Issue', 'Material Receipt', 'Material Transfer', 'Send to Subcontractor'].includes(frm.doc.purpose)) {
-				frm.add_custom_button(__('Bill of Materials'), function() {
-					frm.events.get_items_from_bom(frm);
-				}, __("Get items from"));
+			frm.add_custom_button(__('Bill of Materials'), function() {
+				frm.events.get_items_from_bom(frm);
+			}, __("Get Items From"));
 		}
 	},
 
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py
index 7685267..e3159b9 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.py
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.py
@@ -1227,8 +1227,6 @@
 		return item_dict
 
 	def add_to_stock_entry_detail(self, item_dict, bom_no=None):
-		cost_center = frappe.db.get_value("Company", self.company, 'cost_center')
-
 		for d in item_dict:
 			stock_uom = item_dict[d].get("stock_uom") or frappe.db.get_value("Item", d, "stock_uom")
 
@@ -1239,9 +1237,10 @@
 			se_child.uom = item_dict[d]["uom"] if item_dict[d].get("uom") else stock_uom
 			se_child.stock_uom = stock_uom
 			se_child.qty = flt(item_dict[d]["qty"], se_child.precision("qty"))
-			se_child.cost_center = item_dict[d].get("cost_center") or cost_center
 			se_child.allow_alternative_item = item_dict[d].get("allow_alternative_item", 0)
 			se_child.subcontracted_item = item_dict[d].get("main_item_code")
+			se_child.cost_center = (item_dict[d].get("cost_center") or
+				get_default_cost_center(item_dict[d], company = self.company))
 
 			for field in ["idx", "po_detail", "original_item",
 				"expense_account", "description", "item_name"]:
diff --git a/erpnext/stock/doctype/stock_settings/stock_settings.json b/erpnext/stock/doctype/stock_settings/stock_settings.json
index 067659f..a166657 100644
--- a/erpnext/stock/doctype/stock_settings/stock_settings.json
+++ b/erpnext/stock/doctype/stock_settings/stock_settings.json
@@ -217,7 +217,7 @@
  "index_web_pages_for_search": 1,
  "issingle": 1,
  "links": [],
- "modified": "2020-10-13 10:33:29.147682",
+ "modified": "2020-11-23 15:26:54.225608",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Stock Settings",
@@ -235,5 +235,6 @@
  ],
  "quick_entry": 1,
  "sort_field": "modified",
- "sort_order": "ASC"
+ "sort_order": "ASC",
+ "track_changes": 1
 }
\ No newline at end of file
diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py
index 8d8dcb7..08f7a83 100644
--- a/erpnext/stock/get_item_details.py
+++ b/erpnext/stock/get_item_details.py
@@ -559,23 +559,40 @@
 	else:
 		return None
 
-def get_default_cost_center(args, item, item_group, brand, company=None):
+def get_default_cost_center(args, item=None, item_group=None, brand=None, company=None):
 	cost_center = None
+
+	if not company and args.get("company"):
+		company = args.get("company")
+
 	if args.get('project'):
 		cost_center = frappe.db.get_value("Project", args.get("project"), "cost_center", cache=True)
 
-	if not cost_center:
+	if not cost_center and (item and item_group and brand):
 		if args.get('customer'):
 			cost_center = item.get('selling_cost_center') or item_group.get('selling_cost_center') or brand.get('selling_cost_center')
 		else:
 			cost_center = item.get('buying_cost_center') or item_group.get('buying_cost_center') or brand.get('buying_cost_center')
 
-	cost_center = cost_center or args.get("cost_center")
+	elif not cost_center and args.get("item_code") and company:
+		for method in ["get_item_defaults", "get_item_group_defaults", "get_brand_defaults"]:
+			path = "erpnext.stock.get_item_details.{0}".format(method)
+			data = frappe.get_attr(path)(args.get("item_code"), company)
+
+			if data and (data.selling_cost_center or data.buying_cost_center):
+				return data.selling_cost_center or data.buying_cost_center
+
+	if not cost_center and args.get("cost_center"):
+		cost_center = args.get("cost_center")
 
 	if (company and cost_center
 		and frappe.get_cached_value("Cost Center", cost_center, "company") != company):
 		return None
 
+	if not cost_center and company:
+		cost_center = frappe.get_cached_value("Company",
+			company, "cost_center")
+
 	return cost_center
 
 def get_default_supplier(args, item, item_group, brand):
diff --git a/erpnext/stock/report/stock_ageing/stock_ageing.py b/erpnext/stock/report/stock_ageing/stock_ageing.py
index 3dc806f..8aaf7ab 100644
--- a/erpnext/stock/report/stock_ageing/stock_ageing.py
+++ b/erpnext/stock/report/stock_ageing/stock_ageing.py
@@ -20,7 +20,8 @@
 
 		fifo_queue = sorted(filter(_func, item_dict["fifo_queue"]), key=_func)
 		details = item_dict["details"]
-		if not fifo_queue and (not item_dict.get("total_qty")): continue
+
+		if not fifo_queue: continue
 
 		average_age = get_average_age(fifo_queue, to_date)
 		earliest_age = date_diff(to_date, fifo_queue[0][1])
diff --git a/erpnext/translations/af.csv b/erpnext/translations/af.csv
index 07f81e9..45435d8 100644
--- a/erpnext/translations/af.csv
+++ b/erpnext/translations/af.csv
@@ -4238,7 +4238,6 @@
 End date can not be less than start date,Einddatum kan nie minder wees as die begin datum nie,
 For Default Supplier (Optional),Vir Standaardverskaffer (opsioneel),
 From date cannot be greater than To date,Vanaf datum kan nie groter wees as Datum,
-Get items from,Kry items van,
 Group by,Groep By,
 In stock,In voorraad,
 Item name,Item naam,
@@ -8549,7 +8548,6 @@
 Purchase Receipt Trends,Aankoopontvangstendense,
 Purchase Register,Aankoopregister,
 Quotation Trends,Aanhalingstendense,
-Quoted Item Comparison,Genoteerde Item Vergelyking,
 Received Items To Be Billed,Items ontvang om gefaktureer te word,
 Qty to Order,Hoeveelheid om te bestel,
 Requested Items To Be Transferred,Gevraagde items wat oorgedra moet word,
@@ -9834,3 +9832,9 @@
 Therapy Session overlaps with {0},Terapiesessie oorvleuel met {0},
 Therapy Sessions Overlapping,Terapiesessies oorvleuel,
 Therapy Plans,Terapieplanne,
+"Item Code, warehouse, quantity are required on row {0}","Itemkode, pakhuis, hoeveelheid word in ry {0} vereis",
+Get Items from Material Requests against this Supplier,Kry items uit materiaalversoeke teen hierdie verskaffer,
+Enable European Access,Aktiveer Europese toegang,
+Creating Purchase Order ...,Skep tans bestelling ...,
+"Select a Supplier from the Default Suppliers of the items below. On selection, a Purchase Order will be made against items belonging to the selected Supplier only.",Kies &#39;n verskaffer uit die verstekverskaffers van die onderstaande items. By seleksie sal &#39;n bestelling slegs gemaak word teen items wat tot die geselekteerde verskaffer behoort.,
+Row #{}: You must select {} serial numbers for item {}.,Ry # {}: u moet {} reeksnommers vir item {} kies.,
diff --git a/erpnext/translations/am.csv b/erpnext/translations/am.csv
index 1d0533f..554b0a5 100644
--- a/erpnext/translations/am.csv
+++ b/erpnext/translations/am.csv
@@ -4238,7 +4238,6 @@
 End date can not be less than start date,የማብቂያ ቀን ከመጀመሪያ ቀን ያነሰ መሆን አይችልም,
 For Default Supplier (Optional),ነባሪ አቅራቢ (አማራጭ),
 From date cannot be greater than To date,ቀን ቀን ወደ በላይ ሊሆን አይችልም ከ,
-Get items from,ከ ንጥሎችን ያግኙ,
 Group by,ቡድን በ,
 In stock,ለሽያጭ የቀረበ እቃ,
 Item name,ንጥል ስም,
@@ -8549,7 +8548,6 @@
 Purchase Receipt Trends,የግዢ ደረሰኝ በመታየት ላይ ያሉ,
 Purchase Register,የግዢ ይመዝገቡ,
 Quotation Trends,በትዕምርተ ጥቅስ አዝማሚያዎች,
-Quoted Item Comparison,የተጠቀሰ ንጥል ንጽጽር,
 Received Items To Be Billed,ተቀብሏል ንጥሎች እንዲከፍሉ ለማድረግ,
 Qty to Order,ለማዘዝ ብዛት,
 Requested Items To Be Transferred,ተጠይቋል ንጥሎች መወሰድ,
@@ -9834,3 +9832,9 @@
 Therapy Session overlaps with {0},ቴራፒ ክፍለ-ጊዜ ከ {0} ጋር ይደራረባል,
 Therapy Sessions Overlapping,ቴራፒ ክፍለ-ጊዜዎች መደራረብ,
 Therapy Plans,የሕክምና ዕቅዶች,
+"Item Code, warehouse, quantity are required on row {0}",የእቃ ኮድ ፣ መጋዘን ፣ ብዛት በረድፍ {0} ላይ ያስፈልጋሉ,
+Get Items from Material Requests against this Supplier,በዚህ አቅራቢ ላይ እቃዎችን ከቁሳዊ ጥያቄዎች ያግኙ,
+Enable European Access,የአውሮፓ መዳረሻን ያንቁ,
+Creating Purchase Order ...,የግዢ ትዕዛዝ በመፍጠር ላይ ...,
+"Select a Supplier from the Default Suppliers of the items below. On selection, a Purchase Order will be made against items belonging to the selected Supplier only.",ከዚህ በታች ካሉ ዕቃዎች ነባሪ አቅራቢዎች አቅራቢ ይምረጡ። በምርጫ ወቅት ለተመረጠው አቅራቢ ብቻ በሆኑ ዕቃዎች ላይ የግዢ ትዕዛዝ ይደረጋል።,
+Row #{}: You must select {} serial numbers for item {}.,ረድፍ # {}: {} ለንጥል ተከታታይ ቁጥሮች {} መምረጥ አለብዎት።,
diff --git a/erpnext/translations/ar.csv b/erpnext/translations/ar.csv
index de75e89..91a9da9 100644
--- a/erpnext/translations/ar.csv
+++ b/erpnext/translations/ar.csv
@@ -4238,7 +4238,6 @@
 End date can not be less than start date,تاريخ النهاية لا يمكن أن يكون اقل من تاريخ البدء\n<br>\nEnd Date can not be less than Start Date,
 For Default Supplier (Optional),للمورد الافتراضي (اختياري),
 From date cannot be greater than To date,(من تاريخ) لا يمكن أن يكون أكبر (الي التاريخ),
-Get items from,الحصول على البنود من,
 Group by,المجموعة حسب,
 In stock,في المخزن,
 Item name,اسم السلعة,
@@ -8549,7 +8548,6 @@
 Purchase Receipt Trends,شراء اتجاهات الإيصال,
 Purchase Register,سجل شراء,
 Quotation Trends,مؤشرات المناقصة,
-Quoted Item Comparison,مقارنة بند المناقصة,
 Received Items To Be Billed,العناصر الواردة إلى أن توصف,
 Qty to Order,الكمية للطلب,
 Requested Items To Be Transferred,العناصر المطلوبة على أن يتم تحويلها,
@@ -9834,3 +9832,9 @@
 Therapy Session overlaps with {0},تتداخل جلسة العلاج مع {0},
 Therapy Sessions Overlapping,جلسات العلاج متداخلة,
 Therapy Plans,خطط العلاج,
+"Item Code, warehouse, quantity are required on row {0}",مطلوب رمز الصنف والمستودع والكمية في الصف {0},
+Get Items from Material Requests against this Supplier,الحصول على عناصر من طلبات المواد ضد هذا المورد,
+Enable European Access,تمكين الوصول الأوروبي,
+Creating Purchase Order ...,إنشاء أمر شراء ...,
+"Select a Supplier from the Default Suppliers of the items below. On selection, a Purchase Order will be made against items belonging to the selected Supplier only.",حدد موردًا من الموردين الافتراضيين للعناصر أدناه. عند التحديد ، سيتم إجراء طلب الشراء مقابل العناصر التي تنتمي إلى المورد المحدد فقط.,
+Row #{}: You must select {} serial numbers for item {}.,الصف # {}: يجب تحديد {} الأرقام التسلسلية للعنصر {}.,
diff --git a/erpnext/translations/bg.csv b/erpnext/translations/bg.csv
index 79be6df..15278a6 100644
--- a/erpnext/translations/bg.csv
+++ b/erpnext/translations/bg.csv
@@ -4238,7 +4238,6 @@
 End date can not be less than start date,Крайна дата не може да бъде по-малка от началната дата,
 For Default Supplier (Optional),За доставчик по подразбиране (по избор),
 From date cannot be greater than To date,От дата не може да бъде по-голямо от до дата,
-Get items from,Вземете елементи от,
 Group by,Групирай по,
 In stock,В наличност,
 Item name,Име на артикул,
@@ -8549,7 +8548,6 @@
 Purchase Receipt Trends,Покупка Квитанция Trends,
 Purchase Register,Покупка Регистрация,
 Quotation Trends,Оферта Тенденции,
-Quoted Item Comparison,Сравнение на редове от оферти,
 Received Items To Be Billed,"Приети артикули, които да се фактирират",
 Qty to Order,Количество към поръчка,
 Requested Items To Be Transferred,Желани артикули да бъдат прехвърлени,
@@ -9834,3 +9832,9 @@
 Therapy Session overlaps with {0},Терапевтичната сесия се припокрива с {0},
 Therapy Sessions Overlapping,Терапевтични сесии Припокриване,
 Therapy Plans,Планове за терапия,
+"Item Code, warehouse, quantity are required on row {0}","Код на артикул, склад, количество се изискват на ред {0}",
+Get Items from Material Requests against this Supplier,Вземете артикули от заявки за материали срещу този доставчик,
+Enable European Access,Активирайте европейския достъп,
+Creating Purchase Order ...,Създаване на поръчка ...,
+"Select a Supplier from the Default Suppliers of the items below. On selection, a Purchase Order will be made against items belonging to the selected Supplier only.","Изберете доставчик от доставчиците по подразбиране на елементите по-долу. При избора ще бъде направена Поръчка за покупка срещу артикули, принадлежащи само на избрания Доставчик.",
+Row #{}: You must select {} serial numbers for item {}.,Ред № {}: Трябва да изберете {} серийни номера за артикул {}.,
diff --git a/erpnext/translations/bn.csv b/erpnext/translations/bn.csv
index 1e7413b..cf09716 100644
--- a/erpnext/translations/bn.csv
+++ b/erpnext/translations/bn.csv
@@ -4238,7 +4238,6 @@
 End date can not be less than start date,শেষ তারিখ শুরু তারিখ থেকে কম হতে পারে না,
 For Default Supplier (Optional),ডিফল্ট সরবরাহকারীর জন্য (ঐচ্ছিক),
 From date cannot be greater than To date,তারিখ থেকে তারিখের চেয়ে বেশি হতে পারে না,
-Get items from,থেকে আইটেম পান,
 Group by,গ্রুপ দ্বারা,
 In stock,স্টক ইন,
 Item name,আইটেম নাম,
@@ -8549,7 +8548,6 @@
 Purchase Receipt Trends,কেনার রসিদ প্রবণতা,
 Purchase Register,ক্রয় নিবন্ধন,
 Quotation Trends,উদ্ধৃতি প্রবণতা,
-Quoted Item Comparison,উদ্ধৃত আইটেম তুলনা,
 Received Items To Be Billed,গৃহীত চলছে বিল তৈরি করা,
 Qty to Order,অর্ডার Qty,
 Requested Items To Be Transferred,অনুরোধ করা চলছে স্থানান্তর করা,
@@ -9834,3 +9832,9 @@
 Therapy Session overlaps with {0},থেরাপি সেশন {0 with দিয়ে ওভারল্যাপ করে,
 Therapy Sessions Overlapping,থেরাপি সেশনস ওভারল্যাপিং,
 Therapy Plans,থেরাপি পরিকল্পনা,
+"Item Code, warehouse, quantity are required on row {0}","আইটেম কোড, গুদাম, পরিমাণ সারিতে প্রয়োজন {0}",
+Get Items from Material Requests against this Supplier,এই সরবরাহকারীর বিরুদ্ধে উপাদান অনুরোধগুলি থেকে আইটেমগুলি পান,
+Enable European Access,ইউরোপীয় অ্যাক্সেস সক্ষম করুন,
+Creating Purchase Order ...,ক্রয় ক্রম তৈরি করা হচ্ছে ...,
+"Select a Supplier from the Default Suppliers of the items below. On selection, a Purchase Order will be made against items belonging to the selected Supplier only.","নীচের আইটেমগুলির ডিফল্ট সরবরাহকারী থেকে কোনও সরবরাহকারী নির্বাচন করুন। নির্বাচনের সময়, কেবলমাত্র নির্বাচিত সরবরাহকারীর অন্তর্ভুক্ত আইটেমগুলির বিরুদ্ধে ক্রয় আদেশ দেওয়া হবে।",
+Row #{}: You must select {} serial numbers for item {}.,সারি # {}: আইটেমের জন্য আপনাকে অবশ্যই}} ক্রমিক সংখ্যা নির্বাচন করতে হবে {}।,
diff --git a/erpnext/translations/bs.csv b/erpnext/translations/bs.csv
index 4fec5e0..6ef445a 100644
--- a/erpnext/translations/bs.csv
+++ b/erpnext/translations/bs.csv
@@ -4238,7 +4238,6 @@
 End date can not be less than start date,Datum završetka ne može biti manja od početnog datuma,
 For Default Supplier (Optional),Za podrazumevani dobavljač,
 From date cannot be greater than To date,Od datuma ne može biti veća od To Date,
-Get items from,Get stavke iz,
 Group by,Group By,
 In stock,Na zalihama,
 Item name,Naziv artikla,
@@ -8549,7 +8548,6 @@
 Purchase Receipt Trends,Račun kupnje trendovi,
 Purchase Register,Kupnja Registracija,
 Quotation Trends,Trendovi ponude,
-Quoted Item Comparison,Citirano Stavka Poređenje,
 Received Items To Be Billed,Primljeni Proizvodi se naplaćuje,
 Qty to Order,Količina za narudžbu,
 Requested Items To Be Transferred,Traženi stavki za prijenos,
@@ -9834,3 +9832,9 @@
 Therapy Session overlaps with {0},Sjednica terapije preklapa se sa {0},
 Therapy Sessions Overlapping,Preklapanje terapijskih sesija,
 Therapy Plans,Planovi terapije,
+"Item Code, warehouse, quantity are required on row {0}","Šifra artikla, skladište, količina su obavezni na retku {0}",
+Get Items from Material Requests against this Supplier,Nabavite predmete od materijalnih zahtjeva protiv ovog dobavljača,
+Enable European Access,Omogućiti evropski pristup,
+Creating Purchase Order ...,Kreiranje narudžbenice ...,
+"Select a Supplier from the Default Suppliers of the items below. On selection, a Purchase Order will be made against items belonging to the selected Supplier only.","Odaberite dobavljača od zadanih dobavljača dolje navedenih stavki. Nakon odabira, narudžbenica će se izvršiti samo za proizvode koji pripadaju odabranom dobavljaču.",
+Row #{}: You must select {} serial numbers for item {}.,Red # {}: Morate odabrati {} serijske brojeve za stavku {}.,
diff --git a/erpnext/translations/ca.csv b/erpnext/translations/ca.csv
index 58e6edb..18fa52a 100644
--- a/erpnext/translations/ca.csv
+++ b/erpnext/translations/ca.csv
@@ -4238,7 +4238,6 @@
 End date can not be less than start date,Data de finalització no pot ser inferior a data d'inici,
 For Default Supplier (Optional),Per proveïdor predeterminat (opcional),
 From date cannot be greater than To date,Des de la data no pot ser superior a la data,
-Get items from,Obtenir articles de,
 Group by,Agrupar per,
 In stock,En estoc,
 Item name,Nom de l'article,
@@ -8549,7 +8548,6 @@
 Purchase Receipt Trends,Purchase Receipt Trends,
 Purchase Register,Compra de Registre,
 Quotation Trends,Quotation Trends,
-Quoted Item Comparison,Citat article Comparació,
 Received Items To Be Billed,Articles rebuts per a facturar,
 Qty to Order,Quantitat de comanda,
 Requested Items To Be Transferred,Articles sol·licitats per a ser transferits,
@@ -9834,3 +9832,9 @@
 Therapy Session overlaps with {0},La sessió de teràpia es coincideix amb {0},
 Therapy Sessions Overlapping,Sessions de teràpia superposades,
 Therapy Plans,Plans de teràpia,
+"Item Code, warehouse, quantity are required on row {0}","El codi de l&#39;article, el magatzem, la quantitat són obligatoris a la fila {0}",
+Get Items from Material Requests against this Supplier,Obteniu articles de sol·licituds de material contra aquest proveïdor,
+Enable European Access,Activa l&#39;accés europeu,
+Creating Purchase Order ...,S&#39;està creant una comanda de compra ...,
+"Select a Supplier from the Default Suppliers of the items below. On selection, a Purchase Order will be made against items belonging to the selected Supplier only.","Seleccioneu un proveïdor dels proveïdors predeterminats dels articles següents. En seleccionar-lo, es farà una Comanda de compra únicament contra articles pertanyents al Proveïdor seleccionat.",
+Row #{}: You must select {} serial numbers for item {}.,Fila núm. {}: Heu de seleccionar {} números de sèrie de l&#39;element {}.,
diff --git a/erpnext/translations/cs.csv b/erpnext/translations/cs.csv
index 43fd472..705e471 100644
--- a/erpnext/translations/cs.csv
+++ b/erpnext/translations/cs.csv
@@ -4238,7 +4238,6 @@
 End date can not be less than start date,Datum ukončení nesmí být menší než datum zahájení,
 For Default Supplier (Optional),Výchozí dodavatel (volitelné),
 From date cannot be greater than To date,Od Datum nemůže být větší než Datum,
-Get items from,Položka získaná z,
 Group by,Seskupit podle,
 In stock,Na skladě,
 Item name,Název položky,
@@ -8549,7 +8548,6 @@
 Purchase Receipt Trends,Doklad o koupi Trendy,
 Purchase Register,Nákup Register,
 Quotation Trends,Uvozovky Trendy,
-Quoted Item Comparison,Citoval Položka Porovnání,
 Received Items To Be Billed,"Přijaté položek, které mají být účtovány",
 Qty to Order,Množství k objednávce,
 Requested Items To Be Transferred,Požadované položky mají být převedeny,
@@ -9834,3 +9832,9 @@
 Therapy Session overlaps with {0},Terapie se překrývá s {0},
 Therapy Sessions Overlapping,Terapeutické relace se překrývají,
 Therapy Plans,Terapeutické plány,
+"Item Code, warehouse, quantity are required on row {0}","Na řádku {0} je vyžadován kód položky, sklad, množství",
+Get Items from Material Requests against this Supplier,Získejte položky z materiálových požadavků vůči tomuto dodavateli,
+Enable European Access,Povolit evropský přístup,
+Creating Purchase Order ...,Vytváření nákupní objednávky ...,
+"Select a Supplier from the Default Suppliers of the items below. On selection, a Purchase Order will be made against items belonging to the selected Supplier only.",Vyberte dodavatele z výchozích dodavatelů níže uvedených položek. Při výběru bude provedena objednávka pouze na položky patřící vybranému dodavateli.,
+Row #{}: You must select {} serial numbers for item {}.,Řádek # {}: Musíte vybrat {} sériová čísla pro položku {}.,
diff --git a/erpnext/translations/da.csv b/erpnext/translations/da.csv
index 7222daf..c0d0146 100644
--- a/erpnext/translations/da.csv
+++ b/erpnext/translations/da.csv
@@ -4238,7 +4238,6 @@
 End date can not be less than start date,Slutdato kan ikke være mindre end startdato,
 For Default Supplier (Optional),For standardleverandør (valgfrit),
 From date cannot be greater than To date,Fra dato ikke kan være større end til dato,
-Get items from,Hent varer fra,
 Group by,Sortér efter,
 In stock,På lager,
 Item name,Varenavn,
@@ -8549,7 +8548,6 @@
 Purchase Receipt Trends,Købskvittering Tendenser,
 Purchase Register,Indkøb Register,
 Quotation Trends,Tilbud trends,
-Quoted Item Comparison,Sammenligning Citeret Vare,
 Received Items To Be Billed,Modtagne varer skal faktureres,
 Qty to Order,Antal til ordre,
 Requested Items To Be Transferred,"Anmodet Varer, der skal overføres",
@@ -9834,3 +9832,9 @@
 Therapy Session overlaps with {0},Terapisession overlapper med {0},
 Therapy Sessions Overlapping,Terapisessioner overlapper hinanden,
 Therapy Plans,Terapiplaner,
+"Item Code, warehouse, quantity are required on row {0}","Varekode, lager, antal kræves i række {0}",
+Get Items from Material Requests against this Supplier,Få varer fra materialeanmodninger mod denne leverandør,
+Enable European Access,Aktiver europæisk adgang,
+Creating Purchase Order ...,Opretter indkøbsordre ...,
+"Select a Supplier from the Default Suppliers of the items below. On selection, a Purchase Order will be made against items belonging to the selected Supplier only.","Vælg en leverandør fra standardleverandørerne af nedenstående varer. Ved valg foretages en indkøbsordre kun mod varer, der tilhører den valgte leverandør.",
+Row #{}: You must select {} serial numbers for item {}.,Række nr. {}: Du skal vælge {} serienumre for varen {}.,
diff --git a/erpnext/translations/de.csv b/erpnext/translations/de.csv
index b65c943..ca03a78 100644
--- a/erpnext/translations/de.csv
+++ b/erpnext/translations/de.csv
@@ -4238,7 +4238,6 @@
 End date can not be less than start date,Das Enddatum darf nicht kleiner als das Startdatum sein,
 For Default Supplier (Optional),Für Standardlieferanten (optional),
 From date cannot be greater than To date,Das Ab-Datum kann nicht größer als das Bis-Datum sein,
-Get items from,Holen Sie Elemente aus,
 Group by,Gruppieren nach,
 In stock,Auf Lager,
 Item name,Artikelname,
@@ -8549,7 +8548,6 @@
 Purchase Receipt Trends,Trendanalyse Kaufbelege,
 Purchase Register,Übersicht über Einkäufe,
 Quotation Trends,Trendanalyse Angebote,
-Quoted Item Comparison,Vergleich angebotener Artikel,
 Received Items To Be Billed,"Von Lieferanten gelieferte Artikel, die noch abgerechnet werden müssen",
 Qty to Order,Zu bestellende Menge,
 Requested Items To Be Transferred,"Angeforderte Artikel, die übertragen werden sollen",
@@ -9834,3 +9832,9 @@
 Therapy Session overlaps with {0},Die Therapiesitzung überschneidet sich mit {0},
 Therapy Sessions Overlapping,Überlappende Therapiesitzungen,
 Therapy Plans,Therapiepläne,
+"Item Code, warehouse, quantity are required on row {0}","Artikelcode, Lager, Menge sind in Zeile {0} erforderlich.",
+Get Items from Material Requests against this Supplier,Erhalten Sie Artikel aus Materialanfragen gegen diesen Lieferanten,
+Enable European Access,Ermöglichen Sie den europäischen Zugang,
+Creating Purchase Order ...,Bestellung anlegen ...,
+"Select a Supplier from the Default Suppliers of the items below. On selection, a Purchase Order will be made against items belonging to the selected Supplier only.","Wählen Sie einen Lieferanten aus den Standardlieferanten der folgenden Artikel aus. Bei der Auswahl erfolgt eine Bestellung nur für Artikel, die dem ausgewählten Lieferanten gehören.",
+Row #{}: You must select {} serial numbers for item {}.,Zeile # {}: Sie müssen {} Seriennummern für Artikel {} auswählen.,
diff --git a/erpnext/translations/el.csv b/erpnext/translations/el.csv
index 2db4ac8..acf5db5 100644
--- a/erpnext/translations/el.csv
+++ b/erpnext/translations/el.csv
@@ -4238,7 +4238,6 @@
 End date can not be less than start date,Η ημερομηνία λήξης δεν μπορεί να είναι προγενέστερη της ημερομηνίας έναρξης,
 For Default Supplier (Optional),Για προεπιλεγμένο προμηθευτή (προαιρετικό),
 From date cannot be greater than To date,Από την ημερομηνία αυτή δεν μπορεί να είναι μεταγενέστερη από την έως ημερομηνία,
-Get items from,Πάρτε τα στοιχεία από,
 Group by,Ομαδοποίηση κατά,
 In stock,Σε απόθεμα,
 Item name,Όνομα είδους,
@@ -8549,7 +8548,6 @@
 Purchase Receipt Trends,Τάσεις αποδεικτικού παραλαβής αγοράς,
 Purchase Register,Ταμείο αγορών,
 Quotation Trends,Τάσεις προσφορών,
-Quoted Item Comparison,Εισηγμένες Στοιχείο Σύγκριση,
 Received Items To Be Billed,Είδη που παραλήφθηκαν και πρέπει να τιμολογηθούν,
 Qty to Order,Ποσότητα για παραγγελία,
 Requested Items To Be Transferred,Είδη που ζητήθηκε να μεταφερθούν,
@@ -9834,3 +9832,9 @@
 Therapy Session overlaps with {0},Η συνεδρία θεραπείας αλληλεπικαλύπτεται με {0},
 Therapy Sessions Overlapping,Συνεδρίες συνεδρίας,
 Therapy Plans,Σχέδια θεραπείας,
+"Item Code, warehouse, quantity are required on row {0}","Κωδικός είδους, αποθήκη, ποσότητα απαιτείται στη σειρά {0}",
+Get Items from Material Requests against this Supplier,Λάβετε στοιχεία από αιτήματα υλικών έναντι αυτού του προμηθευτή,
+Enable European Access,Ενεργοποίηση ευρωπαϊκής πρόσβασης,
+Creating Purchase Order ...,Δημιουργία παραγγελίας αγοράς ...,
+"Select a Supplier from the Default Suppliers of the items below. On selection, a Purchase Order will be made against items belonging to the selected Supplier only.","Επιλέξτε έναν προμηθευτή από τους προεπιλεγμένους προμηθευτές των παρακάτω στοιχείων. Κατά την επιλογή, μια εντολή αγοράς θα πραγματοποιείται έναντι αντικειμένων που ανήκουν στον επιλεγμένο Προμηθευτή μόνο.",
+Row #{}: You must select {} serial numbers for item {}.,Σειρά # {}: Πρέπει να επιλέξετε {} σειριακούς αριθμούς για το στοιχείο {}.,
diff --git a/erpnext/translations/es.csv b/erpnext/translations/es.csv
index be195aa..0f2259d 100644
--- a/erpnext/translations/es.csv
+++ b/erpnext/translations/es.csv
@@ -421,7 +421,7 @@
 Bundle items at time of sale.,Agrupe elementos al momento de la venta.,
 Business Development Manager,Gerente de Desarrollo de Negocios,
 Buy,Comprar,
-Buying,Comprando,
+Buying,Compras,
 Buying Amount,Importe de compra,
 Buying Price List,Lista de precios de compra,
 Buying Rate,Tipo de Cambio de Compra,
@@ -535,7 +535,7 @@
 Claimed Amount,Cantidad reclamada,
 Clay,Arcilla,
 Clear filters,Filtros claros,
-Clear values,Valores claros,
+Clear values,Quitar valores,
 Clearance Date,Fecha de liquidación,
 Clearance Date not mentioned,Fecha de liquidación no definida,
 Clearance Date updated,Fecha de liquidación actualizada,
@@ -728,7 +728,7 @@
 Current Qty,Cant. Actual,
 Current invoice {0} is missing,La factura actual {0} falta,
 Custom HTML,HTML Personalizado,
-Custom?,Personalizado?,
+Custom?,¿Personalizado?,
 Customer,Cliente,
 Customer Addresses And Contacts,Direcciones de clientes y contactos,
 Customer Contact,Contacto del Cliente,
@@ -783,7 +783,7 @@
 Default BOM ({0}) must be active for this item or its template,La lista de materiales (LdM) por defecto ({0}) debe estar activa para este producto o plantilla,
 Default BOM for {0} not found,BOM por defecto para {0} no encontrado,
 Default BOM not found for Item {0} and Project {1},La lista de materiales predeterminada no se encontró para el Elemento {0} y el Proyecto {1},
-Default Letter Head,Encabezado predeterminado,
+Default Letter Head,Encabezado Predeterminado,
 Default Tax Template,Plantilla de impuesto predeterminado,
 Default Unit of Measure for Item {0} cannot be changed directly because you have already made some transaction(s) with another UOM. You will need to create a new Item to use a different Default UOM.,Unidad de medida predeterminada para el artículo {0} no se puede cambiar directamente porque ya ha realizado alguna transacción (s) con otra UOM. Usted tendrá que crear un nuevo elemento a utilizar un UOM predeterminado diferente.,
 Default Unit of Measure for Variant '{0}' must be same as in Template '{1}',Unidad de medida predeterminada para variante '{0}' debe ser la mismo que en la plantilla '{1}',
@@ -966,7 +966,7 @@
 Error Log,Registro de Errores,
 Error evaluating the criteria formula,Error al evaluar la fórmula de criterios,
 Error in formula or condition: {0},Error Fórmula o Condición: {0},
-Error: Not a valid id?,Error: No es un ID válido?,
+Error: Not a valid id?,Error: ¿No es un ID válido?,
 Estimated Cost,Costo estimado,
 Evaluation,Evaluación,
 "Even if there are multiple Pricing Rules with highest priority, then following internal priorities are applied:","Incluso si hay varias reglas de precios con mayor prioridad, se aplican entonces siguientes prioridades internas:",
@@ -1338,7 +1338,7 @@
 Issued,Emitido,
 Issues,Incidencias,
 It is needed to fetch Item Details.,Se necesita a buscar Detalles del artículo.,
-Item,Productos,
+Item,Producto,
 Item 1,Elemento 1,
 Item 2,Elemento 2,
 Item 3,Elemento 3,
@@ -1426,7 +1426,7 @@
 Last Purchase Rate,Tasa de cambio de última compra,
 Latest,Más reciente,
 Latest price updated in all BOMs,Último precio actualizado en todas las Listas de Materiales,
-Lead,Dirigir,
+Lead,Iniciativa,
 Lead Count,Cuenta de Iniciativa,
 Lead Owner,Propietario de la iniciativa,
 Lead Owner cannot be same as the Lead,Propietario de Iniciativa no puede ser igual que el de la Iniciativa,
@@ -1535,7 +1535,7 @@
 Mark Half Day,Marcar medio día,
 Mark Present,Marcar Presente,
 Marketing,Márketing,
-Marketing Expenses,GASTOS DE PUBLICIDAD,
+Marketing Expenses,Gastos de Publicidad,
 Marketplace,Mercado,
 Marketplace Error,Error de Marketplace,
 Masters,Maestros,
@@ -1867,7 +1867,7 @@
 Part-time,Tiempo parcial,
 Partially Depreciated,Despreciables Parcialmente,
 Partially Received,Parcialmente recibido,
-Party,Partido,
+Party,Tercero,
 Party Name,Nombre de Parte,
 Party Type,Tipo de entidad,
 Party Type and Party is mandatory for {0} account,Tipo de Tercero y Tercero es obligatorio para la Cuenta {0},
@@ -2027,7 +2027,7 @@
 Please select Completion Date for Completed Asset Maintenance Log,Seleccione Fecha de Finalización para el Registro de Mantenimiento de Activos Completado,
 Please select Completion Date for Completed Repair,Seleccione Fecha de Finalización para la Reparación Completa,
 Please select Course,Por favor seleccione Curso,
-Please select Drug,Seleccione Droga,
+Please select Drug,Por favor seleccione fármaco,
 Please select Employee,Por favor selecciona Empleado,
 Please select Existing Company for creating Chart of Accounts,"Por favor, seleccione empresa ya existente para la creación del plan de cuentas",
 Please select Healthcare Service,Por favor seleccione Servicio de Salud,
@@ -2118,7 +2118,7 @@
 Please supply the specified items at the best possible rates,Por favor suministrar los elementos especificados en las mejores tasas posibles,
 Please update your status for this training event,Actualice su estado para este evento de capacitación.,
 Please wait 3 days before resending the reminder.,Espere 3 días antes de volver a enviar el recordatorio.,
-Point of Sale,Punto de venta,
+Point of Sale,Punto de Venta,
 Point-of-Sale,Punto de Venta (POS),
 Point-of-Sale Profile,Perfiles de punto de venta (POS),
 Portal,Portal,
@@ -2627,7 +2627,7 @@
 Selling,Ventas,
 Selling Amount,Cantidad de venta,
 Selling Price List,Lista de precios de venta,
-Selling Rate,Tasa de ventas,
+Selling Rate,Precio de venta,
 "Selling must be checked, if Applicable For is selected as {0}","'Ventas' debe ser seleccionada, si la opción: 'Aplicable para' esta seleccionado como {0}",
 Send Grant Review Email,Enviar correo electrónico de revisión de subvención,
 Send Now,Enviar ahora,
@@ -2700,9 +2700,9 @@
 Setup default values for POS Invoices,Configurar los valores predeterminados para facturas de POS,
 Setup mode of POS (Online / Offline),Modo de configuración de POS (Online / Offline),
 Setup your Institute in ERPNext,Configura tu instituto en ERPNext,
-Share Balance,Compartir Saldo,
+Share Balance,Balance de Acciones,
 Share Ledger,Share Ledger,
-Share Management,Gestión de Compartir,
+Share Management,Administración de Acciones,
 Share Transfer,Transferir Acciones,
 Share Type,Tipo de acción,
 Shareholder,Accionista,
@@ -3302,7 +3302,7 @@
 White,Blanco,
 Wire Transfer,Transferencia bancaria,
 WooCommerce Products,Productos WooCommerce,
-Work In Progress,Trabajo en progreso,
+Work In Progress,Trabajo en Proceso,
 Work Order,Orden de trabajo,
 Work Order already created for all items with BOM,Órden de Trabajo ya creada para todos los artículos con lista de materiales,
 Work Order cannot be raised against a Item Template,La Órden de Trabajo no puede levantarse contra una Plantilla de Artículo,
@@ -3582,7 +3582,7 @@
 Accounting Period overlaps with {0},El período contable se superpone con {0},
 Activity,Actividad,
 Add / Manage Email Accounts.,Añadir / Administrar cuentas de correo electrónico.,
-Add Child,Agregar niño,
+Add Child,Agregar hijo,
 Add Loan Security,Agregar seguridad de préstamo,
 Add Multiple,Añadir Multiple,
 Add Participants,Agregar Participantes,
@@ -3706,7 +3706,7 @@
 Designation,Puesto,
 Difference Value,Valor de diferencia,
 Dimension Filter,Filtro de dimensiones,
-Disabled,Discapacitado,
+Disabled,Deshabilitado,
 Disbursement and Repayment,Desembolso y reembolso,
 Distance cannot be greater than 4000 kms,La distancia no puede ser mayor a 4000 kms,
 Do you want to submit the material request,¿Quieres enviar la solicitud de material?,
@@ -4193,7 +4193,7 @@
 Barcode,Código de barras,
 Bold,Negrita,
 Center,Centro,
-Clear,Claro,
+Clear,Quitar,
 Comment,Comentario,
 Comments,Comentarios,
 DocType,DocType,
@@ -4238,7 +4238,6 @@
 End date can not be less than start date,la fecha final no puede ser inferior a fecha de Inicio,
 For Default Supplier (Optional),Para el proveedor predeterminado (opcional),
 From date cannot be greater than To date,La fecha 'Desde' no puede ser mayor que la fecha 'Hasta',
-Get items from,Obtener artículos de,
 Group by,Agrupar por,
 In stock,En stock,
 Item name,Nombre del producto,
@@ -4305,7 +4304,7 @@
 Invalid Account,Cuenta no válida,
 Purchase Order Required,Orden de compra requerida,
 Purchase Receipt Required,Recibo de compra requerido,
-Account Missing,Falta la cuenta,
+Account Missing,Cuenta Faltante,
 Requested,Solicitado,
 Partially Paid,Parcialmente pagado,
 Invalid Account Currency,Moneda de la cuenta no válida,
@@ -5600,7 +5599,7 @@
 Received By,Recibido por,
 Caller Information,Información de la llamada,
 Contact Name,Nombre de contacto,
-Lead ,Dirigir,
+Lead ,Iniciativa,
 Lead Name,Nombre de la iniciativa,
 Ringing,Zumbido,
 Missed,Perdido,
@@ -6619,7 +6618,7 @@
 Total Experience,Experiencia total,
 Default Leave Policy,Política de Licencia Predeterminada,
 Default Salary Structure,Estructura de Salario Predeterminada,
-Employee Group Table,Mesa de grupo de empleados,
+Employee Group Table,Tabla de grupo de empleados,
 ERPNext User ID,ERP ID de usuario siguiente,
 Employee Health Insurance,Seguro de Salud para Empleados,
 Health Insurance Name,Nombre del Seguro de Salud,
@@ -6838,10 +6837,10 @@
 Number Of Employees,Número de Empleados,
 Employee Details,Detalles del Empleado,
 Validate Attendance,Validar la Asistencia,
-Salary Slip Based on Timesheet,Nomina basada en el Parte de Horas,
+Salary Slip Based on Timesheet,Nomina basada horas,
 Select Payroll Period,Seleccione el Período de Nómina,
 Deduct Tax For Unclaimed Employee Benefits,Deducir Impuestos para beneficios de Empleados no Reclamados,
-Deduct Tax For Unsubmitted Tax Exemption Proof,Deducir impuestos por prueba de exención de impuestos sin enviar,
+Deduct Tax For Unsubmitted Tax Exemption Proof,Deducir impuestos por soporte de exención de impuestos sin enviar,
 Select Payment Account to make Bank Entry,Seleccionar la cuenta de pago para hacer la entrada del Banco,
 Salary Slips Created,Salario Slips creado,
 Salary Slips Submitted,Nómina Salarial Validada,
@@ -7093,7 +7092,7 @@
 Loan Manager,Gerente de préstamos,
 Loan Info,Información del Préstamo,
 Rate of Interest,Tasa de interés,
-Proposed Pledges,Promesas Propuestas,
+Proposed Pledges,Prendas Propuestas,
 Maximum Loan Amount,Cantidad máxima del préstamo,
 Repayment Info,Información de la Devolución,
 Total Payable Interest,Interés Total a Pagar,
@@ -7340,7 +7339,7 @@
 Available Qty at WIP Warehouse,Cantidad Disponible en Almacén WIP,
 Work Order Operation,Operación de Órden de Trabajo,
 Operation Description,Descripción de la operación,
-Operation completed for how many finished goods?,Se completo la operación para la cantidad de productos terminados?,
+Operation completed for how many finished goods?,¿Operación completada para cuántos productos terminados?,
 Work in Progress,Trabajo en proceso,
 Estimated Time and Cost,Tiempo estimado y costo,
 Planned Start Time,Hora prevista de inicio,
@@ -8452,7 +8451,7 @@
 Asset Depreciations and Balances,Depreciaciones de Activos y Saldos,
 Available Stock for Packing Items,Inventario Disponible de Artículos de Embalaje,
 Bank Clearance Summary,Resumen de Cambios Bancarios,
-Bank Remittance,Remesa bancaria,
+Bank Remittance,Giro Bancario,
 Batch Item Expiry Status,Estado de Caducidad de Lote de Productos,
 Batch-Wise Balance History,Historial de Saldo por Lotes,
 BOM Explorer,BOM Explorer,
@@ -8549,7 +8548,6 @@
 Purchase Receipt Trends,Tendencias de recibos de compra,
 Purchase Register,Registro de compras,
 Quotation Trends,Tendencias de Presupuestos,
-Quoted Item Comparison,Comparación de artículos de Cotización,
 Received Items To Be Billed,Recepciones por facturar,
 Qty to Order,Cantidad a Solicitar,
 Requested Items To Be Transferred,Artículos solicitados para ser transferidos,
@@ -9834,3 +9832,9 @@
 Therapy Session overlaps with {0},La sesión de terapia se superpone con {0},
 Therapy Sessions Overlapping,Superposición de sesiones de terapia,
 Therapy Plans,Planes de terapia,
+"Item Code, warehouse, quantity are required on row {0}","El código de artículo, el almacén y la cantidad son obligatorios en la fila {0}",
+Get Items from Material Requests against this Supplier,Obtener artículos de solicitudes de material contra este proveedor,
+Enable European Access,Habilitar el acceso europeo,
+Creating Purchase Order ...,Creando orden de compra ...,
+"Select a Supplier from the Default Suppliers of the items below. On selection, a Purchase Order will be made against items belonging to the selected Supplier only.","Seleccione un proveedor de los proveedores predeterminados de los artículos a continuación. En la selección, se realizará una orden de compra contra los artículos que pertenecen al proveedor seleccionado únicamente.",
+Row #{}: You must select {} serial numbers for item {}.,Fila # {}: debe seleccionar {} números de serie para el artículo {}.,
diff --git a/erpnext/translations/es_ar.csv b/erpnext/translations/es_ar.csv
index 9bdcba1..1fd8723 100644
--- a/erpnext/translations/es_ar.csv
+++ b/erpnext/translations/es_ar.csv
@@ -1,5 +1,4 @@
 Employee {0} on Half day on {1},"Empleado {0}, media jornada el día {1}",
-Item,Producto,
 Communication,Comunicacion,
 Components,Componentes,
 Cheque Size,Tamaño de Cheque,
diff --git a/erpnext/translations/es_gt.csv b/erpnext/translations/es_gt.csv
index efd2daa..29ce2b8 100644
--- a/erpnext/translations/es_gt.csv
+++ b/erpnext/translations/es_gt.csv
@@ -1,4 +1,3 @@
-Item,Producto,
 Lead Time Days,Tiempo de ejecución en días,
 Outstanding,Pendiente,
 Outstanding Amount,Saldo Pendiente,
diff --git a/erpnext/translations/et.csv b/erpnext/translations/et.csv
index b778eff..ba32187 100644
--- a/erpnext/translations/et.csv
+++ b/erpnext/translations/et.csv
@@ -4238,7 +4238,6 @@
 End date can not be less than start date,End Date saa olla väiksem kui alguskuupäev,
 For Default Supplier (Optional),Vaikimisi tarnija (valikuline),
 From date cannot be greater than To date,Siit kuupäev ei saa olla suurem kui kuupäev,
-Get items from,Võta esemed,
 Group by,Group By,
 In stock,Laos,
 Item name,Toote nimi,
@@ -8549,7 +8548,6 @@
 Purchase Receipt Trends,Ostutšekk Trends,
 Purchase Register,Ostu Registreeri,
 Quotation Trends,Tsitaat Trends,
-Quoted Item Comparison,Tsiteeritud Punkt võrdlus,
 Received Items To Be Billed,Saadud objekte arve,
 Qty to Order,Kogus tellida,
 Requested Items To Be Transferred,Taotletud üleantavate,
@@ -9834,3 +9832,9 @@
 Therapy Session overlaps with {0},Teraapiaseanss kattub rakendusega {0},
 Therapy Sessions Overlapping,Teraapiaseansid kattuvad,
 Therapy Plans,Teraapiakavad,
+"Item Code, warehouse, quantity are required on row {0}","Real {0} on nõutav kaubakood, ladu ja kogus",
+Get Items from Material Requests against this Supplier,Hankige esemeid selle tarnija vastu esitatud materjalitaotlustest,
+Enable European Access,Luba Euroopa juurdepääs,
+Creating Purchase Order ...,Ostutellimuse loomine ...,
+"Select a Supplier from the Default Suppliers of the items below. On selection, a Purchase Order will be made against items belonging to the selected Supplier only.",Valige allpool olevate üksuste vaiketarnijatest tarnija. Valiku alusel tehakse ostutellimus ainult valitud tarnijale kuuluvate kaupade kohta.,
+Row #{}: You must select {} serial numbers for item {}.,Rida nr {}: peate valima {} üksuse seerianumbrid {}.,
diff --git a/erpnext/translations/fa.csv b/erpnext/translations/fa.csv
index 0e4d19a..4a7c979 100644
--- a/erpnext/translations/fa.csv
+++ b/erpnext/translations/fa.csv
@@ -4238,7 +4238,6 @@
 End date can not be less than start date,تاریخ پایان نمی تواند کمتر از تاریخ شروع,
 For Default Supplier (Optional),برای تامین کننده پیش فرض (اختیاری),
 From date cannot be greater than To date,از تاریخ نمی تواند بیشتر از تاریخ باشد,
-Get items from,گرفتن اقلام از,
 Group by,گروه توسط,
 In stock,در انبار,
 Item name,نام آیتم,
@@ -8549,7 +8548,6 @@
 Purchase Receipt Trends,روند رسید خرید,
 Purchase Register,خرید ثبت نام,
 Quotation Trends,روند نقل قول,
-Quoted Item Comparison,مورد نقل مقایسه,
 Received Items To Be Billed,دریافت گزینه هایی که صورتحساب,
 Qty to Order,تعداد سفارش,
 Requested Items To Be Transferred,آیتم ها درخواست می شود منتقل,
@@ -9834,3 +9832,9 @@
 Therapy Session overlaps with {0},جلسه درمانی با {0} همپوشانی دارد,
 Therapy Sessions Overlapping,جلسات درمانی با هم تداخل دارند,
 Therapy Plans,برنامه های درمانی,
+"Item Code, warehouse, quantity are required on row {0}",کد مورد ، انبار ، مقدار در ردیف {0} لازم است,
+Get Items from Material Requests against this Supplier,مواردی را از درخواستهای ماده در برابر این تأمین کننده دریافت کنید,
+Enable European Access,دسترسی اروپا را فعال کنید,
+Creating Purchase Order ...,در حال ایجاد سفارش خرید ...,
+"Select a Supplier from the Default Suppliers of the items below. On selection, a Purchase Order will be made against items belonging to the selected Supplier only.",از تامین کنندگان پیش فرض موارد زیر یک تأمین کننده انتخاب کنید. هنگام انتخاب ، سفارش خرید فقط در مورد کالاهای متعلق به تنها تامین کننده انتخاب شده انجام می شود.,
+Row #{}: You must select {} serial numbers for item {}.,ردیف شماره {}: شما باید {} شماره سریال را برای مورد {} انتخاب کنید.,
diff --git a/erpnext/translations/fi.csv b/erpnext/translations/fi.csv
index 23fd7a7..29eb567 100644
--- a/erpnext/translations/fi.csv
+++ b/erpnext/translations/fi.csv
@@ -4238,7 +4238,6 @@
 End date can not be less than start date,päättymispäivä ei voi olla ennen aloituspäivää,
 For Default Supplier (Optional),Oletuksena toimittaja (valinnainen),
 From date cannot be greater than To date,Alkaen päivä ei voi olla suurempi kuin päättymispäivä,
-Get items from,Hae nimikkeet,
 Group by,ryhmän,
 In stock,Varastossa,
 Item name,Nimikkeen nimi,
@@ -8549,7 +8548,6 @@
 Purchase Receipt Trends,Saapumisten kehitys,
 Purchase Register,Osto Rekisteröidy,
 Quotation Trends,Tarjousten kehitys,
-Quoted Item Comparison,Noteeratut Kohta Vertailu,
 Received Items To Be Billed,Saivat kohteet laskuttamat,
 Qty to Order,Tilattava yksikkömäärä,
 Requested Items To Be Transferred,siirrettävät pyydetyt tuotteet,
@@ -9834,3 +9832,9 @@
 Therapy Session overlaps with {0},Hoitoistunto on päällekkäinen kohteen {0} kanssa,
 Therapy Sessions Overlapping,Hoitoistunnot ovat päällekkäisiä,
 Therapy Plans,Hoitosuunnitelmat,
+"Item Code, warehouse, quantity are required on row {0}","Tuotekoodi, varasto, määrä vaaditaan rivillä {0}",
+Get Items from Material Requests against this Supplier,Hanki tuotteita tältä toimittajalta saaduista materiaalipyynnöistä,
+Enable European Access,Ota käyttöön eurooppalainen käyttöoikeus,
+Creating Purchase Order ...,Luodaan ostotilausta ...,
+"Select a Supplier from the Default Suppliers of the items below. On selection, a Purchase Order will be made against items belonging to the selected Supplier only.",Valitse toimittaja alla olevien tuotteiden oletustoimittajista. Valinnan yhteydessä ostotilaus tehdään vain valitulle toimittajalle kuuluvista tuotteista.,
+Row #{}: You must select {} serial numbers for item {}.,Rivi # {}: Sinun on valittava {} tuotteen sarjanumerot {}.,
diff --git a/erpnext/translations/fr.csv b/erpnext/translations/fr.csv
index 09a9033..3cdae45 100644
--- a/erpnext/translations/fr.csv
+++ b/erpnext/translations/fr.csv
@@ -583,7 +583,7 @@
 Configure,Configurer,
 Configure {0},Configurer {0},
 Confirmed orders from Customers.,Commandes confirmées des clients.,
-Connect Amazon with ERPNext,Connectez Amazon avec ERPNext,
+Connect Amazon with ERPNext,Connecter Amazon avec ERPNext,
 Connect Shopify with ERPNext,Connectez Shopify avec ERPNext,
 Connect to Quickbooks,Se connecter à Quickbooks,
 Connected to QuickBooks,Connecté à QuickBooks,
@@ -4238,7 +4238,6 @@
 End date can not be less than start date,La date de Fin ne peut pas être antérieure à la Date de Début,
 For Default Supplier (Optional),Pour le fournisseur par défaut (facultatif),
 From date cannot be greater than To date,La Date Initiale ne peut pas être postérieure à la Date Finale,
-Get items from,Obtenir les articles de,
 Group by,Grouper Par,
 In stock,En stock,
 Item name,Nom de l'article,
@@ -8549,7 +8548,6 @@
 Purchase Receipt Trends,Tendances des Reçus d'Achats,
 Purchase Register,Registre des Achats,
 Quotation Trends,Tendances des Devis,
-Quoted Item Comparison,Comparaison d'Article Soumis,
 Received Items To Be Billed,Articles Reçus à Facturer,
 Qty to Order,Quantité à Commander,
 Requested Items To Be Transferred,Articles Demandés à Transférer,
@@ -9834,3 +9832,9 @@
 Therapy Session overlaps with {0},La session de thérapie chevauche {0},
 Therapy Sessions Overlapping,Chevauchement des séances de thérapie,
 Therapy Plans,Plans de thérapie,
+"Item Code, warehouse, quantity are required on row {0}","Le code article, l&#39;entrepôt et la quantité sont obligatoires sur la ligne {0}",
+Get Items from Material Requests against this Supplier,Obtenir des articles à partir de demandes d&#39;articles auprès de ce fournisseur,
+Enable European Access,Activer l&#39;accès européen,
+Creating Purchase Order ...,Création d&#39;une commande d&#39;achat ...,
+"Select a Supplier from the Default Suppliers of the items below. On selection, a Purchase Order will be made against items belonging to the selected Supplier only.","Sélectionnez un fournisseur parmi les fournisseurs par défaut des articles ci-dessous. Lors de la sélection, un bon de commande sera effectué contre des articles appartenant uniquement au fournisseur sélectionné.",
+Row #{}: You must select {} serial numbers for item {}.,Ligne n ° {}: vous devez sélectionner {} numéros de série pour l&#39;article {}.,
diff --git a/erpnext/translations/gu.csv b/erpnext/translations/gu.csv
index e25c6bb..5c2b520 100644
--- a/erpnext/translations/gu.csv
+++ b/erpnext/translations/gu.csv
@@ -4238,7 +4238,6 @@
 End date can not be less than start date,સમાપ્તિ તારીખ પ્રારંભ તારીખ કરતાં ઓછી હોઈ શકતી નથી,
 For Default Supplier (Optional),ડિફોલ્ટ સપ્લાયર માટે (વૈકલ્પિક),
 From date cannot be greater than To date,તારીખથી તારીખ કરતાં વધુ હોઈ શકતી નથી,
-Get items from,વસ્તુઓ મેળવો,
 Group by,ગ્રુપ દ્વારા,
 In stock,ઉપલબ્ધ છે,
 Item name,વસ્તુ નામ,
@@ -8549,7 +8548,6 @@
 Purchase Receipt Trends,ખરીદી રસીદ પ્રવાહો,
 Purchase Register,ખરીદી રજીસ્ટર,
 Quotation Trends,અવતરણ પ્રવાહો,
-Quoted Item Comparison,નોંધાયેલા વસ્તુ સરખામણી,
 Received Items To Be Billed,પ્રાપ્ત વસ્તુઓ બિલ કરવા,
 Qty to Order,ઓર્ડર Qty,
 Requested Items To Be Transferred,વિનંતી વસ્તુઓ ટ્રાન્સફર કરી,
@@ -9834,3 +9832,9 @@
 Therapy Session overlaps with {0},ઉપચાર સત્ર {0 with સાથે ઓવરલેપ થાય છે,
 Therapy Sessions Overlapping,ઉપચાર સત્રો ઓવરલેપિંગ,
 Therapy Plans,ઉપચાર યોજનાઓ,
+"Item Code, warehouse, quantity are required on row {0}","આઇટમ કોડ, વેરહાઉસ, જથ્થો પંક્તિ પર આવશ્યક છે {0}",
+Get Items from Material Requests against this Supplier,આ સપ્લાયર સામે સામગ્રી વિનંતીઓમાંથી આઇટમ્સ મેળવો,
+Enable European Access,યુરોપિયન Enableક્સેસને સક્ષમ કરો,
+Creating Purchase Order ...,ખરીદી Orderર્ડર બનાવી રહ્યાં છે ...,
+"Select a Supplier from the Default Suppliers of the items below. On selection, a Purchase Order will be made against items belonging to the selected Supplier only.","નીચેની આઇટમ્સના ડિફaultલ્ટ સપ્લાયર્સમાંથી સપ્લાયર પસંદ કરો. પસંદગી પર, ફક્ત પસંદ કરેલા સપ્લાયરની વસ્તુઓ સામે ખરીદ ઓર્ડર આપવામાં આવશે.",
+Row #{}: You must select {} serial numbers for item {}.,પંક્તિ # {}: તમારે આઇટમ for for માટે સીરીયલ નંબરો પસંદ કરવા આવશ્યક છે.,
diff --git a/erpnext/translations/he.csv b/erpnext/translations/he.csv
index 43ca52c..29e6f6a 100644
--- a/erpnext/translations/he.csv
+++ b/erpnext/translations/he.csv
@@ -4238,7 +4238,6 @@
 End date can not be less than start date,תאריך סיום לא יכול להיות פחות מתאריך ההתחלה,
 For Default Supplier (Optional),לספק ברירת מחדל (אופציונלי),
 From date cannot be greater than To date,מתאריך לא יכול להיות גדול יותר מאשר תאריך,
-Get items from,קבל פריטים מ,
 Group by,קבוצה על ידי,
 In stock,במלאי,
 Item name,שם פריט,
@@ -8549,7 +8548,6 @@
 Purchase Receipt Trends,מגמות קבלת רכישה,
 Purchase Register,רכישת הרשמה,
 Quotation Trends,מגמות ציטוט,
-Quoted Item Comparison,פריט מצוטט השוואה,
 Received Items To Be Billed,פריטים שהתקבלו לחיוב,
 Qty to Order,כמות להזמנה,
 Requested Items To Be Transferred,פריטים מבוקשים שיועברו,
@@ -9834,3 +9832,9 @@
 Therapy Session overlaps with {0},מושב טיפולי חופף עם {0},
 Therapy Sessions Overlapping,מפגשי טיפול חופפים,
 Therapy Plans,תוכניות טיפול,
+"Item Code, warehouse, quantity are required on row {0}","קוד פריט, מחסן, כמות נדרשים בשורה {0}",
+Get Items from Material Requests against this Supplier,קבל פריטים מבקשות חומר נגד ספק זה,
+Enable European Access,אפשר גישה אירופית,
+Creating Purchase Order ...,יוצר הזמנת רכש ...,
+"Select a Supplier from the Default Suppliers of the items below. On selection, a Purchase Order will be made against items belonging to the selected Supplier only.","בחר ספק מבין ספקי ברירת המחדל של הפריטים למטה. בבחירה, הזמנת רכש תתבצע כנגד פריטים השייכים לספק שנבחר בלבד.",
+Row #{}: You must select {} serial numbers for item {}.,שורה מספר {}: עליך לבחור {} מספרים סידוריים לפריט {}.,
diff --git a/erpnext/translations/hi.csv b/erpnext/translations/hi.csv
index c18532b..c385fc6 100644
--- a/erpnext/translations/hi.csv
+++ b/erpnext/translations/hi.csv
@@ -4238,7 +4238,6 @@
 End date can not be less than start date,समाप्ति तिथि आरंभ तिथि से कम नहीं हो सकता,
 For Default Supplier (Optional),डिफ़ॉल्ट प्रदायक (वैकल्पिक) के लिए,
 From date cannot be greater than To date,दिनांक से दिनांक से अधिक नहीं हो सकता है,
-Get items from,से आइटम प्राप्त,
 Group by,समूह द्वारा,
 In stock,स्टॉक में,
 Item name,मद का नाम,
@@ -8549,7 +8548,6 @@
 Purchase Receipt Trends,खरीद रसीद रुझान,
 Purchase Register,इन पंजीकृत खरीद,
 Quotation Trends,कोटेशन रुझान,
-Quoted Item Comparison,उद्धरित मद तुलना,
 Received Items To Be Billed,बिल करने के लिए प्राप्त आइटम,
 Qty to Order,मात्रा आदेश को,
 Requested Items To Be Transferred,हस्तांतरित करने का अनुरोध आइटम,
@@ -9834,3 +9832,9 @@
 Therapy Session overlaps with {0},थेरेपी सत्र {0} से ओवरलैप होता है,
 Therapy Sessions Overlapping,थेरेपी सेशन ओवरलैपिंग,
 Therapy Plans,थेरेपी योजनाएं,
+"Item Code, warehouse, quantity are required on row {0}","पंक्ति {0} पर आइटम कोड, गोदाम, मात्रा आवश्यक है",
+Get Items from Material Requests against this Supplier,इस आपूर्तिकर्ता के विरुद्ध सामग्री अनुरोध से आइटम प्राप्त करें,
+Enable European Access,यूरोपीय पहुँच सक्षम करें,
+Creating Purchase Order ...,क्रय आदेश बनाना ...,
+"Select a Supplier from the Default Suppliers of the items below. On selection, a Purchase Order will be made against items belonging to the selected Supplier only.","नीचे दी गई वस्तुओं के डिफ़ॉल्ट आपूर्तिकर्ता से एक आपूर्तिकर्ता का चयन करें। चयन पर, केवल चयनित आपूर्तिकर्ता से संबंधित वस्तुओं के खिलाफ एक खरीद ऑर्डर किया जाएगा।",
+Row #{}: You must select {} serial numbers for item {}.,पंक्ति # {}: आपको आइटम {} के लिए {} सीरियल नंबर का चयन करना होगा।,
diff --git a/erpnext/translations/hr.csv b/erpnext/translations/hr.csv
index aabacdc..a544e98 100644
--- a/erpnext/translations/hr.csv
+++ b/erpnext/translations/hr.csv
@@ -4238,7 +4238,6 @@
 End date can not be less than start date,Datum završetka ne može biti manja od početnog datuma,
 For Default Supplier (Optional),Za dobavljača zadano (neobavezno),
 From date cannot be greater than To date,Datum ne može biti veći od datuma,
-Get items from,Nabavite stavke iz,
 Group by,Grupiranje prema,
 In stock,Na lageru,
 Item name,Naziv proizvoda,
@@ -8549,7 +8548,6 @@
 Purchase Receipt Trends,Trend primki,
 Purchase Register,Popis nabave,
 Quotation Trends,Trend ponuda,
-Quoted Item Comparison,Citirano predmeta za usporedbu,
 Received Items To Be Billed,Primljeni Proizvodi se naplaćuje,
 Qty to Order,Količina za narudžbu,
 Requested Items To Be Transferred,Traženi proizvodi spremni za transfer,
@@ -9834,3 +9832,9 @@
 Therapy Session overlaps with {0},Sjednica terapije preklapa se s {0},
 Therapy Sessions Overlapping,Preklapajuće se terapijske sesije,
 Therapy Plans,Planovi terapije,
+"Item Code, warehouse, quantity are required on row {0}","Šifra artikla, skladište, količina potrebni su na retku {0}",
+Get Items from Material Requests against this Supplier,Nabavite stavke iz materijalnih zahtjeva protiv ovog dobavljača,
+Enable European Access,Omogućiti europski pristup,
+Creating Purchase Order ...,Izrada narudžbenice ...,
+"Select a Supplier from the Default Suppliers of the items below. On selection, a Purchase Order will be made against items belonging to the selected Supplier only.","Odaberite dobavljača od zadanih dobavljača dolje navedenih stavki. Nakon odabira, narudžbenica će se izvršiti samo za proizvode koji pripadaju odabranom dobavljaču.",
+Row #{}: You must select {} serial numbers for item {}.,Redak {{}: Morate odabrati {} serijske brojeve za stavku {}.,
diff --git a/erpnext/translations/hu.csv b/erpnext/translations/hu.csv
index 09acda3..29f347e 100644
--- a/erpnext/translations/hu.csv
+++ b/erpnext/translations/hu.csv
@@ -4238,7 +4238,6 @@
 End date can not be less than start date,"A befejezés dátuma nem lehet kevesebb, mint a kezdő dátum",
 For Default Supplier (Optional),Az alapértelmezett beszállító számára (opcionális),
 From date cannot be greater than To date,"A dátum nem lehet nagyobb, mint a dátum",
-Get items from,Tételeket kér le innen,
 Group by,Csoportosítva,
 In stock,Raktáron,
 Item name,Tétel neve,
@@ -8549,7 +8548,6 @@
 Purchase Receipt Trends,Beszerzési nyugták alakulása,
 Purchase Register,Beszerzési Regisztráció,
 Quotation Trends,Árajánlatok alakulása,
-Quoted Item Comparison,Ajánlott tétel összehasonlítás,
 Received Items To Be Billed,Számlázandó Beérkezett tételek,
 Qty to Order,Mennyiség Rendeléshez,
 Requested Items To Be Transferred,Kérte az átvinni kívánt elemeket,
@@ -9834,3 +9832,9 @@
 Therapy Session overlaps with {0},A terápiás munkamenet átfedésben van a következővel: {0},
 Therapy Sessions Overlapping,A terápiás foglalkozások átfedésben vannak,
 Therapy Plans,Terápiás tervek,
+"Item Code, warehouse, quantity are required on row {0}","A (z) {0} sorban tételszám, raktár, mennyiség szükséges",
+Get Items from Material Requests against this Supplier,Tételeket szerezhet a szállítóval szembeni anyagi igényekből,
+Enable European Access,Engedélyezze az európai hozzáférést,
+Creating Purchase Order ...,Megrendelés létrehozása ...,
+"Select a Supplier from the Default Suppliers of the items below. On selection, a Purchase Order will be made against items belonging to the selected Supplier only.",Válasszon szállítót az alábbi elemek alapértelmezett szállítói közül. A kiválasztáskor csak a kiválasztott szállítóhoz tartozó termékekre készül megrendelés.,
+Row #{}: You must select {} serial numbers for item {}.,#. Sor:} {0} sorszámokat kell kiválasztania.,
diff --git a/erpnext/translations/id.csv b/erpnext/translations/id.csv
index 53122cc..7175ad2 100644
--- a/erpnext/translations/id.csv
+++ b/erpnext/translations/id.csv
@@ -4238,7 +4238,6 @@
 End date can not be less than start date,Tanggal Berakhir tidak boleh kurang dari Tanggal Mulai,
 For Default Supplier (Optional),Untuk Pemasok Default (Opsional),
 From date cannot be greater than To date,Dari Tanggal tidak dapat lebih besar dari To Date,
-Get items from,Mendapatkan Stok Barang-Stok Barang dari,
 Group by,Kelompok Dengan,
 In stock,Persediaan,
 Item name,Nama Item,
@@ -8549,7 +8548,6 @@
 Purchase Receipt Trends,Tren Nota Penerimaan,
 Purchase Register,Register Pembelian,
 Quotation Trends,Trend Penawaran,
-Quoted Item Comparison,Perbandingan Produk/Barang yang ditawarkan,
 Received Items To Be Billed,Produk Diterima Akan Ditagih,
 Qty to Order,Kuantitas untuk diorder,
 Requested Items To Be Transferred,Permintaan Produk Akan Ditransfer,
@@ -9834,3 +9832,9 @@
 Therapy Session overlaps with {0},Sesi Terapi tumpang tindih dengan {0},
 Therapy Sessions Overlapping,Sesi Terapi Tumpang Tindih,
 Therapy Plans,Rencana Terapi,
+"Item Code, warehouse, quantity are required on row {0}","Kode Barang, gudang, kuantitas diperlukan di baris {0}",
+Get Items from Material Requests against this Supplier,Dapatkan Item dari Permintaan Material terhadap Pemasok ini,
+Enable European Access,Aktifkan Akses Eropa,
+Creating Purchase Order ...,Membuat Pesanan Pembelian ...,
+"Select a Supplier from the Default Suppliers of the items below. On selection, a Purchase Order will be made against items belonging to the selected Supplier only.","Pilih Pemasok dari Pemasok Default item di bawah ini. Saat dipilih, Pesanan Pembelian akan dibuat terhadap barang-barang milik Pemasok terpilih saja.",
+Row #{}: You must select {} serial numbers for item {}.,Baris # {}: Anda harus memilih {} nomor seri untuk item {}.,
diff --git a/erpnext/translations/is.csv b/erpnext/translations/is.csv
index 50828ba..5f56aff 100644
--- a/erpnext/translations/is.csv
+++ b/erpnext/translations/is.csv
@@ -4238,7 +4238,6 @@
 End date can not be less than start date,Lokadagur getur ekki verið minna en upphafsdagur,
 For Default Supplier (Optional),Fyrir Sjálfgefið Birgir (valfrjálst),
 From date cannot be greater than To date,Frá Dagsetning má ekki vera meiri en Til Dagsetning,
-Get items from,Fá atriði úr,
 Group by,Hópa eftir,
 In stock,Á lager,
 Item name,Item Name,
@@ -8549,7 +8548,6 @@
 Purchase Receipt Trends,Kvittun Trends,
 Purchase Register,kaup Register,
 Quotation Trends,Tilvitnun Trends,
-Quoted Item Comparison,Vitnað Item Samanburður,
 Received Items To Be Billed,Móttekin Items verður innheimt,
 Qty to Order,Magn til að panta,
 Requested Items To Be Transferred,Umbeðin Items til að flytja,
@@ -9834,3 +9832,9 @@
 Therapy Session overlaps with {0},Meðferðarlotan skarast við {0},
 Therapy Sessions Overlapping,Meðferðarlotur skarast,
 Therapy Plans,Meðferðaráætlanir,
+"Item Code, warehouse, quantity are required on row {0}","Vörukóði, vöruhús, magn er krafist í línu {0}",
+Get Items from Material Requests against this Supplier,Fáðu hluti frá beiðnum um efni gagnvart þessum birgi,
+Enable European Access,Virkja evrópskan aðgang,
+Creating Purchase Order ...,Býr til innkaupapöntun ...,
+"Select a Supplier from the Default Suppliers of the items below. On selection, a Purchase Order will be made against items belonging to the selected Supplier only.",Veldu birgja frá sjálfgefnum birgjum hlutanna hér að neðan. Við val verður eingöngu gerð innkaupapöntun á hlutum sem tilheyra völdum birgi.,
+Row #{}: You must select {} serial numbers for item {}.,Röð nr. {}: Þú verður að velja {} raðnúmer fyrir hlut {}.,
diff --git a/erpnext/translations/it.csv b/erpnext/translations/it.csv
index 4da11f1..3a1d73f 100644
--- a/erpnext/translations/it.csv
+++ b/erpnext/translations/it.csv
@@ -4238,7 +4238,6 @@
 End date can not be less than start date,Data di Fine non può essere inferiore a Data di inizio,
 For Default Supplier (Optional),Per fornitore predefinito (facoltativo),
 From date cannot be greater than To date,Dalla data non può essere maggiore di Alla data,
-Get items from,Ottenere elementi dal,
 Group by,Raggruppa per,
 In stock,disponibile,
 Item name,Nome Articolo,
@@ -8549,7 +8548,6 @@
 Purchase Receipt Trends,Acquisto Tendenze Receipt,
 Purchase Register,Registro Acquisti,
 Quotation Trends,Tendenze di preventivo,
-Quoted Item Comparison,Articolo Citato Confronto,
 Received Items To Be Billed,Oggetti ricevuti da fatturare,
 Qty to Order,Qtà da Ordinare,
 Requested Items To Be Transferred,Voci si chiede il trasferimento,
@@ -9834,3 +9832,9 @@
 Therapy Session overlaps with {0},La sessione di terapia si sovrappone a {0},
 Therapy Sessions Overlapping,Sessioni di terapia sovrapposte,
 Therapy Plans,Piani terapeutici,
+"Item Code, warehouse, quantity are required on row {0}","Codice articolo, magazzino e quantità sono obbligatori nella riga {0}",
+Get Items from Material Requests against this Supplier,Ottieni articoli da richieste di materiale contro questo fornitore,
+Enable European Access,Consentire l&#39;accesso europeo,
+Creating Purchase Order ...,Creazione dell&#39;ordine di acquisto ...,
+"Select a Supplier from the Default Suppliers of the items below. On selection, a Purchase Order will be made against items belonging to the selected Supplier only.","Seleziona un fornitore dai fornitori predefiniti degli articoli seguenti. Alla selezione, verrà effettuato un Ordine di acquisto solo per gli articoli appartenenti al Fornitore selezionato.",
+Row #{}: You must select {} serial numbers for item {}.,Riga # {}: è necessario selezionare i {} numeri di serie per l&#39;articolo {}.,
diff --git a/erpnext/translations/ja.csv b/erpnext/translations/ja.csv
index 3fa1c18..6e2eaae 100644
--- a/erpnext/translations/ja.csv
+++ b/erpnext/translations/ja.csv
@@ -4238,7 +4238,6 @@
 End date can not be less than start date,終了日は開始日より短くすることはできません,
 For Default Supplier (Optional),デフォルトサプライヤ(オプション),
 From date cannot be greater than To date,開始日を終了日より大きくすることはできません,
-Get items from,アイテム取得元,
 Group by,グループ化,
 In stock,在庫あり,
 Item name,アイテム名,
@@ -8549,7 +8548,6 @@
 Purchase Receipt Trends,領収書傾向,
 Purchase Register,仕入帳,
 Quotation Trends,見積傾向,
-Quoted Item Comparison,引用符で囲まれた項目の比較,
 Received Items To Be Billed,支払予定受領アイテム,
 Qty to Order,注文数,
 Requested Items To Be Transferred,移転予定の要求アイテム,
@@ -9834,3 +9832,9 @@
 Therapy Session overlaps with {0},セラピーセッションが{0}と重複しています,
 Therapy Sessions Overlapping,重複する治療セッション,
 Therapy Plans,治療計画,
+"Item Code, warehouse, quantity are required on row {0}",行{0}にはアイテムコード、倉庫、数量が必要です,
+Get Items from Material Requests against this Supplier,このサプライヤーに対する重要な要求からアイテムを取得する,
+Enable European Access,ヨーロッパへのアクセスを有効にする,
+Creating Purchase Order ...,注文書の作成..。,
+"Select a Supplier from the Default Suppliers of the items below. On selection, a Purchase Order will be made against items belonging to the selected Supplier only.",以下の項目のデフォルトサプライヤーからサプライヤーを選択します。選択時に、選択したサプライヤーに属するアイテムに対してのみ発注書が作成されます。,
+Row #{}: You must select {} serial numbers for item {}.,行#{}:アイテム{}の{}シリアル番号を選択する必要があります。,
diff --git a/erpnext/translations/km.csv b/erpnext/translations/km.csv
index e1a01b0..e2a528c 100644
--- a/erpnext/translations/km.csv
+++ b/erpnext/translations/km.csv
@@ -4238,7 +4238,6 @@
 End date can not be less than start date,កាលបរិច្ឆេទបញ្ចប់មិនអាចតិចជាងកាលបរិច្ឆេទចាប់ផ្ដើមទេ,
 For Default Supplier (Optional),សម្រាប់អ្នកផ្គត់ផ្គង់លំនាំដើម (ស្រេចចិត្ត),
 From date cannot be greater than To date,ពីកាលបរិច្ឆេទមិនអាចមានចំនួនច្រើនជាងកាលបរិច្ឆេទ,
-Get items from,ទទួលបានមុខទំនិញពី,
 Group by,ក្រុមតាម,
 In stock,នៅក្នុងស្តុក,
 Item name,ឈ្មោះធាតុ,
@@ -8549,7 +8548,6 @@
 Purchase Receipt Trends,និន្នាការបង្កាន់ដៃទិញ,
 Purchase Register,ទិញចុះឈ្មោះ,
 Quotation Trends,សម្រង់និន្នាការ,
-Quoted Item Comparison,ធាតុដកស្រង់សម្តីប្រៀបធៀប,
 Received Items To Be Billed,ទទួលបានធាតុដែលនឹងត្រូវបានផ្សព្វផ្សាយ,
 Qty to Order,qty ម៉ង់ទិញ,
 Requested Items To Be Transferred,ធាតុដែលបានស្នើសុំឱ្យគេបញ្ជូន,
@@ -9834,3 +9832,9 @@
 Therapy Session overlaps with {0},វគ្គនៃការព្យាបាលត្រួតគ្នាជាមួយ {0},
 Therapy Sessions Overlapping,ការព្យាបាលដោយការត្រួតគ្នា,
 Therapy Plans,ផែនការព្យាបាល,
+"Item Code, warehouse, quantity are required on row {0}",លេខកូដទំនិញឃ្លាំងបរិមាណត្រូវបានទាមទារនៅជួរ {0},
+Get Items from Material Requests against this Supplier,ទទួលបានវត្ថុពីសំណើសម្ភារៈប្រឆាំងនឹងអ្នកផ្គត់ផ្គង់នេះ,
+Enable European Access,បើកដំណើរការចូលអឺរ៉ុប,
+Creating Purchase Order ...,កំពុងបង្កើតការបញ្ជាទិញ ...,
+"Select a Supplier from the Default Suppliers of the items below. On selection, a Purchase Order will be made against items belonging to the selected Supplier only.",ជ្រើសរើសអ្នកផ្គត់ផ្គង់ពីអ្នកផ្គត់ផ្គង់លំនាំដើមនៃធាតុខាងក្រោម។ នៅពេលជ្រើសរើសការបញ្ជាទិញនឹងត្រូវធ្វើឡើងប្រឆាំងនឹងរបស់របរដែលជាកម្មសិទ្ធិរបស់អ្នកផ្គត់ផ្គង់ដែលបានជ្រើសរើសតែប៉ុណ្ណោះ។,
+Row #{}: You must select {} serial numbers for item {}.,ជួរទី # {}៖ អ្នកត្រូវតែជ្រើសរើស {} លេខស៊េរីសម្រាប់ធាតុ {} ។,
diff --git a/erpnext/translations/kn.csv b/erpnext/translations/kn.csv
index fdd798d..4a9173d 100644
--- a/erpnext/translations/kn.csv
+++ b/erpnext/translations/kn.csv
@@ -4238,7 +4238,6 @@
 End date can not be less than start date,ಅಂತಿಮ ದಿನಾಂಕ ಪ್ರಾರಂಭ ದಿನಾಂಕಕ್ಕಿಂತ ಕಡಿಮೆ ಇರುವಂತಿಲ್ಲ,
 For Default Supplier (Optional),ಡೀಫಾಲ್ಟ್ ಪೂರೈಕೆದಾರರಿಗಾಗಿ (ಐಚ್ಛಿಕ),
 From date cannot be greater than To date,ದಿನಾಂಕದಿಂದ ದಿನಾಂಕಕ್ಕಿಂತಲೂ ಹೆಚ್ಚಿನದಾಗಿರುವಂತಿಲ್ಲ,
-Get items from,ಐಟಂಗಳನ್ನು ಪಡೆಯಿರಿ,
 Group by,ಗುಂಪಿನ,
 In stock,ಉಪಲಬ್ದವಿದೆ,
 Item name,ಐಟಂ ಹೆಸರು,
@@ -8549,7 +8548,6 @@
 Purchase Receipt Trends,ಖರೀದಿ ರಸೀತಿ ಟ್ರೆಂಡ್ಸ್,
 Purchase Register,ಖರೀದಿ ನೋಂದಣಿ,
 Quotation Trends,ನುಡಿಮುತ್ತುಗಳು ಟ್ರೆಂಡ್ಸ್,
-Quoted Item Comparison,ಉಲ್ಲೇಖಿಸಿದ ಐಟಂ ಹೋಲಿಕೆ,
 Received Items To Be Billed,ಪಾವತಿಸಬೇಕಾಗುತ್ತದೆ ಸ್ವೀಕರಿಸಿದ ಐಟಂಗಳು,
 Qty to Order,ಪ್ರಮಾಣ ಆರ್ಡರ್,
 Requested Items To Be Transferred,ಬದಲಾಯಿಸಿಕೊಳ್ಳುವಂತೆ ವಿನಂತಿಸಲಾಗಿದೆ ಐಟಂಗಳು,
@@ -9834,3 +9832,9 @@
 Therapy Session overlaps with {0},ಥೆರಪಿ ಸೆಷನ್ {0 with ನೊಂದಿಗೆ ಅತಿಕ್ರಮಿಸುತ್ತದೆ,
 Therapy Sessions Overlapping,ಥೆರಪಿ ಸೆಷನ್‌ಗಳು ಅತಿಕ್ರಮಿಸುತ್ತವೆ,
 Therapy Plans,ಚಿಕಿತ್ಸೆಯ ಯೋಜನೆಗಳು,
+"Item Code, warehouse, quantity are required on row {0}","Code 0 row ಸಾಲಿನಲ್ಲಿ ಐಟಂ ಕೋಡ್, ಗೋದಾಮು, ಪ್ರಮಾಣ ಅಗತ್ಯವಿದೆ",
+Get Items from Material Requests against this Supplier,ಈ ಸರಬರಾಜುದಾರರ ವಿರುದ್ಧ ವಸ್ತು ವಿನಂತಿಗಳಿಂದ ವಸ್ತುಗಳನ್ನು ಪಡೆಯಿರಿ,
+Enable European Access,ಯುರೋಪಿಯನ್ ಪ್ರವೇಶವನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿ,
+Creating Purchase Order ...,ಖರೀದಿ ಆದೇಶವನ್ನು ರಚಿಸಲಾಗುತ್ತಿದೆ ...,
+"Select a Supplier from the Default Suppliers of the items below. On selection, a Purchase Order will be made against items belonging to the selected Supplier only.","ಕೆಳಗಿನ ಐಟಂಗಳ ಡೀಫಾಲ್ಟ್ ಪೂರೈಕೆದಾರರಿಂದ ಸರಬರಾಜುದಾರರನ್ನು ಆಯ್ಕೆಮಾಡಿ. ಆಯ್ಕೆಯ ಮೇಲೆ, ಆಯ್ದ ಸರಬರಾಜುದಾರರಿಗೆ ಮಾತ್ರ ಸೇರಿದ ವಸ್ತುಗಳ ವಿರುದ್ಧ ಖರೀದಿ ಆದೇಶವನ್ನು ಮಾಡಲಾಗುತ್ತದೆ.",
+Row #{}: You must select {} serial numbers for item {}.,ಸಾಲು # {}: ನೀವು item item ಐಟಂಗೆ {} ಸರಣಿ ಸಂಖ್ಯೆಗಳನ್ನು ಆರಿಸಬೇಕು.,
diff --git a/erpnext/translations/ko.csv b/erpnext/translations/ko.csv
index 1ba119c..c051b07 100644
--- a/erpnext/translations/ko.csv
+++ b/erpnext/translations/ko.csv
@@ -4238,7 +4238,6 @@
 End date can not be less than start date,종료일은 시작일보다 짧을 수 없습니다.,
 For Default Supplier (Optional),기본 공급 업체 (선택 사항),
 From date cannot be greater than To date,날짜에서 날짜보다 클 수 없습니다,
-Get items from,에서 항목을 가져 오기,
 Group by,그룹으로,
 In stock,재고,
 Item name,품명,
@@ -8549,7 +8548,6 @@
 Purchase Receipt Trends,구매 영수증 동향,
 Purchase Register,회원에게 구매,
 Quotation Trends,견적 동향,
-Quoted Item Comparison,인용 상품 비교,
 Received Items To Be Billed,청구에 주어진 항목,
 Qty to Order,수량은 주문,
 Requested Items To Be Transferred,전송할 요청 항목,
@@ -9834,3 +9832,9 @@
 Therapy Session overlaps with {0},치료 세션이 {0}와 (과) 겹칩니다.,
 Therapy Sessions Overlapping,겹치는 치료 세션,
 Therapy Plans,치료 계획,
+"Item Code, warehouse, quantity are required on row {0}","{0} 행에 품목 코드, 창고, 수량이 필요합니다.",
+Get Items from Material Requests against this Supplier,이 공급자에 대한 자재 요청에서 품목 가져 오기,
+Enable European Access,유럽 액세스 활성화,
+Creating Purchase Order ...,구매 오더 생성 ...,
+"Select a Supplier from the Default Suppliers of the items below. On selection, a Purchase Order will be made against items belonging to the selected Supplier only.",아래 항목의 기본 공급자에서 공급자를 선택합니다. 선택시 선택한 공급 업체에 속한 품목에 대해서만 구매 주문이 작성됩니다.,
+Row #{}: You must select {} serial numbers for item {}.,행 # {} : 항목 {}에 대해 {} 일련 번호를 선택해야합니다.,
diff --git a/erpnext/translations/ku.csv b/erpnext/translations/ku.csv
index 5d9d472..6962ea1 100644
--- a/erpnext/translations/ku.csv
+++ b/erpnext/translations/ku.csv
@@ -4238,7 +4238,6 @@
 End date can not be less than start date,Dîrok Dîroka Destpêk Destpêk Dibe,
 For Default Supplier (Optional),Ji bo Default Supplier (alternatîf),
 From date cannot be greater than To date,Ji Date ne dikarin bibin mezintir To Date,
-Get items from,Get tomar ji,
 Group by,Koma By,
 In stock,Ez bêzarim,
 Item name,Navê Navekî,
@@ -8549,7 +8548,6 @@
 Purchase Receipt Trends,Trends kirînê Meqbûz,
 Purchase Register,Buy Register,
 Quotation Trends,Trends quotation,
-Quoted Item Comparison,Babetê têbinî eyna,
 Received Items To Be Billed,Pêşwaziya Nawy ye- Be,
 Qty to Order,Qty siparîş,
 Requested Items To Be Transferred,Nawy xwestin veguhestin,
@@ -9834,3 +9832,9 @@
 Therapy Session overlaps with {0},Danişîna Terapiyê bi {0} re li hevûdu dike,
 Therapy Sessions Overlapping,Danişînên Terapiyê Li Hev Dikevin,
 Therapy Plans,Planên Terapiyê,
+"Item Code, warehouse, quantity are required on row {0}","Koda tiştê, embarê, hejmar li ser rêzê hewce ne {0}",
+Get Items from Material Requests against this Supplier,Li dijî vê Pêşkêşkerê Tiştan ji Daxwazên Maddî bistînin,
+Enable European Access,Destûra Ewropî çalak bikin,
+Creating Purchase Order ...,Afirandina Biryara Kirînê ...,
+"Select a Supplier from the Default Suppliers of the items below. On selection, a Purchase Order will be made against items belonging to the selected Supplier only.","Ji Pargîdaniyên Pêşwext ên jêrîn ve Pêşkêşvanek hilbijêrin. Li ser hilbijartinê, dê Biryarnameyek Kirînê li dijî tiştên ku tenê ji Pêşkêşkarê hilbijartî ne pêk were.",
+Row #{}: You must select {} serial numbers for item {}.,Rêzok # {}: Divê hûn {} hejmarên rêzê ji bo hêmanê {} hilbijêrin.,
diff --git a/erpnext/translations/lo.csv b/erpnext/translations/lo.csv
index 2220ac3..b61476c 100644
--- a/erpnext/translations/lo.csv
+++ b/erpnext/translations/lo.csv
@@ -4238,7 +4238,6 @@
 End date can not be less than start date,ວັນສິ້ນສຸດບໍ່ສາມາດນ້ອຍກວ່າວັນເລີ່ມຕົ້ນ,
 For Default Supplier (Optional),ສໍາລັບຜູ້ໃຫ້ບໍລິການມາດຕະຖານ (ທາງເລືອກ),
 From date cannot be greater than To date,ຈາກວັນທີບໍ່ສາມາດຈະມີຫຼາຍຂຶ້ນກ່ວາເຖິງວັນທີ່,
-Get items from,ໄດ້ຮັບການລາຍການຈາກ,
 Group by,ກຸ່ມໂດຍ,
 In stock,ໃນສາງ,
 Item name,ຊື່ສິນຄ້າ,
@@ -8549,7 +8548,6 @@
 Purchase Receipt Trends,ແນວໂນ້ມການຊື້ຮັບ,
 Purchase Register,ລົງທະບຽນການຊື້,
 Quotation Trends,ແນວໂນ້ມວົງຢືມ,
-Quoted Item Comparison,ປຽບທຽບບາຍດີທຸກທ່ານ Item,
 Received Items To Be Billed,ລາຍການທີ່ໄດ້ຮັບການໄດ້ຮັບການ billed,
 Qty to Order,ຈໍານວນທີ່ຈະສັ່ງຊື້ສິນຄ້າ,
 Requested Items To Be Transferred,ການຮ້ອງຂໍໃຫ້ໄດ້ຮັບການໂອນ,
@@ -9834,3 +9832,9 @@
 Therapy Session overlaps with {0},Therapy Session ຊ້ ຳ ກັບ {0},
 Therapy Sessions Overlapping,ການປິ່ນປົວດ້ວຍການຊໍ້າຊ້ອນ,
 Therapy Plans,ແຜນການປິ່ນປົວ,
+"Item Code, warehouse, quantity are required on row {0}","ລະຫັດສິນຄ້າ, ຄັງສິນຄ້າ, ຈຳ ນວນທີ່ຕ້ອງການຢູ່ແຖວ {0}",
+Get Items from Material Requests against this Supplier,ໄດ້ຮັບສິນຄ້າຈາກຂໍ້ຮຽກຮ້ອງດ້ານວັດຖຸຕໍ່ຜູ້ສະ ໜອງ ນີ້,
+Enable European Access,ເປີດໃຊ້ງານ European Access,
+Creating Purchase Order ...,ການສ້າງໃບສັ່ງຊື້ ...,
+"Select a Supplier from the Default Suppliers of the items below. On selection, a Purchase Order will be made against items belonging to the selected Supplier only.","ເລືອກຜູ້ສະ ໜອງ ສິນຄ້າຈາກຜູ້ສະ ໜອງ ສິນຄ້າເລີ່ມຕົ້ນຂອງລາຍການຂ້າງລຸ່ມນີ້. ໃນການເລືອກ, ຄຳ ສັ່ງຊື້ສິນຄ້າຈະຖືກຕໍ່ຕ້ານກັບສິນຄ້າທີ່ເປັນຂອງຜູ້ສະ ໜອງ ທີ່ຖືກຄັດເລືອກເທົ່ານັ້ນ.",
+Row #{}: You must select {} serial numbers for item {}.,ແຖວ # {}: ທ່ານຕ້ອງເລືອກ {} ເລກ ລຳ ດັບ ສຳ ລັບລາຍການ {}.,
diff --git a/erpnext/translations/lt.csv b/erpnext/translations/lt.csv
index e98f2f2..78571f9 100644
--- a/erpnext/translations/lt.csv
+++ b/erpnext/translations/lt.csv
@@ -4238,7 +4238,6 @@
 End date can not be less than start date,Galutinė data negali būti mažesnė už pradžios datą,
 For Default Supplier (Optional),Numatytam tiekėjui (neprivaloma),
 From date cannot be greater than To date,Nuo datos negali būti didesnis nei iki datos,
-Get items from,Gauk elementus iš,
 Group by,Grupuoti pagal,
 In stock,Sandelyje,
 Item name,Daikto pavadinimas,
@@ -8549,7 +8548,6 @@
 Purchase Receipt Trends,Pirkimo kvito tendencijos,
 Purchase Register,pirkimo Registruotis,
 Quotation Trends,Kainų tendencijos,
-Quoted Item Comparison,Cituojamas punktas Palyginimas,
 Received Items To Be Billed,Gauti duomenys turi būti apmokestinama,
 Qty to Order,Kiekis užsisakyti,
 Requested Items To Be Transferred,Pageidaujami daiktai turi būti perkeltos,
@@ -9834,3 +9832,9 @@
 Therapy Session overlaps with {0},Terapijos seansas sutampa su {0},
 Therapy Sessions Overlapping,Terapijos seansai sutampa,
 Therapy Plans,Terapijos planai,
+"Item Code, warehouse, quantity are required on row {0}","Prekės kodas, sandėlis, kiekis būtini {0} eilutėje",
+Get Items from Material Requests against this Supplier,Gaukite elementus iš šio tiekėjo materialinių užklausų,
+Enable European Access,Įgalinti Europos prieigą,
+Creating Purchase Order ...,Kuriamas pirkimo užsakymas ...,
+"Select a Supplier from the Default Suppliers of the items below. On selection, a Purchase Order will be made against items belonging to the selected Supplier only.","Pasirinkite tiekėją iš toliau nurodytų gaminių iš numatytųjų tiekėjų. Pasirinkus pirkimą, bus sudarytos tik prekės, priklausančios pasirinktam tiekėjui.",
+Row #{}: You must select {} serial numbers for item {}.,# Eilutė {}: turite pasirinkti {} prekės serijos numerius {}.,
diff --git a/erpnext/translations/lv.csv b/erpnext/translations/lv.csv
index 5fdedc8..cbf0485 100644
--- a/erpnext/translations/lv.csv
+++ b/erpnext/translations/lv.csv
@@ -4238,7 +4238,6 @@
 End date can not be less than start date,Beigu Datums nevar būt mazāks par sākuma datuma,
 For Default Supplier (Optional),Paredzētajam piegādātājam (neobligāti),
 From date cannot be greater than To date,No datuma nevar būt lielāka par datumu,
-Get items from,Dabūtu preces no,
 Group by,Group By,
 In stock,Noliktavā,
 Item name,Vienības nosaukums,
@@ -8549,7 +8548,6 @@
 Purchase Receipt Trends,Pirkuma čeka tendences,
 Purchase Register,Pirkuma Reģistrēties,
 Quotation Trends,Piedāvājumu tendences,
-Quoted Item Comparison,Citēts Prece salīdzinājums,
 Received Items To Be Billed,Saņemtie posteņi ir Jāmaksā,
 Qty to Order,Daudz pasūtījuma,
 Requested Items To Be Transferred,Pieprasīto pozīcijas jāpārskaita,
@@ -9834,3 +9832,9 @@
 Therapy Session overlaps with {0},Terapijas sesija pārklājas ar {0},
 Therapy Sessions Overlapping,Terapijas sesijas pārklājas,
 Therapy Plans,Terapijas plāni,
+"Item Code, warehouse, quantity are required on row {0}","Rindā {0} ir nepieciešams preces kods, noliktava un daudzums",
+Get Items from Material Requests against this Supplier,Iegūstiet preces no materiāliem pieprasījumiem pret šo piegādātāju,
+Enable European Access,Iespējot Eiropas piekļuvi,
+Creating Purchase Order ...,Notiek pirkuma pasūtījuma izveide ...,
+"Select a Supplier from the Default Suppliers of the items below. On selection, a Purchase Order will be made against items belonging to the selected Supplier only.","Izvēlieties piegādātāju no tālāk norādīto vienumu noklusējuma piegādātājiem. Pēc izvēles tiks veikts pirkuma pasūtījums tikai par precēm, kas pieder izvēlētajam piegādātājam.",
+Row #{}: You must select {} serial numbers for item {}.,#. Rinda: jums jāizvēlas {} vienuma sērijas numuri {}.,
diff --git a/erpnext/translations/mk.csv b/erpnext/translations/mk.csv
index fa3de63..7008025 100644
--- a/erpnext/translations/mk.csv
+++ b/erpnext/translations/mk.csv
@@ -4238,7 +4238,6 @@
 End date can not be less than start date,Крајниот датум не може да биде помал од датумот на почеток,
 For Default Supplier (Optional),За стандарден добавувач (опционално),
 From date cannot be greater than To date,Од датумот не може да биде поголем од датум,
-Get items from,Се предмети од,
 Group by,Со група,
 In stock,На залиха,
 Item name,Точка Име,
@@ -8549,7 +8548,6 @@
 Purchase Receipt Trends,Купување Потврда трендови,
 Purchase Register,Купување Регистрирај се,
 Quotation Trends,Трендови на Понуди,
-Quoted Item Comparison,Цитирано Точка споредба,
 Received Items To Be Billed,Примените предмети да бидат фактурирани,
 Qty to Order,Количина да нарачате,
 Requested Items To Be Transferred,Бара предмети да бидат префрлени,
@@ -9834,3 +9832,9 @@
 Therapy Session overlaps with {0},Сесијата за терапија се преклопува со {0},
 Therapy Sessions Overlapping,Сесии за терапија што се преклопуваат,
 Therapy Plans,Планови за терапија,
+"Item Code, warehouse, quantity are required on row {0}","Кодот на објектот, складиштето, количината се потребни на редот {0}",
+Get Items from Material Requests against this Supplier,Набавете предмети од материјални барања против овој добавувач,
+Enable European Access,Овозможете европски пристап,
+Creating Purchase Order ...,Создавање налог за набавка ...,
+"Select a Supplier from the Default Suppliers of the items below. On selection, a Purchase Order will be made against items belonging to the selected Supplier only.","Изберете снабдувач од Стандардните добавувачи на ставките подолу. При избор, ќе се изврши Нарачка за набавка само на предмети што припаѓаат на избраниот Добавувач.",
+Row #{}: You must select {} serial numbers for item {}.,Ред # {}: Мора да изберете {} сериски броеви за ставка {}.,
diff --git a/erpnext/translations/ml.csv b/erpnext/translations/ml.csv
index 6c9bcfc..f917969 100644
--- a/erpnext/translations/ml.csv
+++ b/erpnext/translations/ml.csv
@@ -4238,7 +4238,6 @@
 End date can not be less than start date,അവസാന തീയതി ആരംഭ തീയതിക്ക് കുറവായിരിക്കരുത്,
 For Default Supplier (Optional),സ്ഥിര വിതരണക്കാരന് (ഓപ്ഷണൽ),
 From date cannot be greater than To date,തീയതി മുതൽ തീയതി വരെ വലിയതായിരിക്കരുത്,
-Get items from,നിന്ന് ഇനങ്ങൾ നേടുക,
 Group by,ഗ്രൂപ്പ്,
 In stock,സ്റ്റോക്കുണ്ട്,
 Item name,ഇനം പേര്,
@@ -8549,7 +8548,6 @@
 Purchase Receipt Trends,വാങ്ങൽ രസീത് ട്രെൻഡുകൾ,
 Purchase Register,രജിസ്റ്റർ വാങ്ങുക,
 Quotation Trends,ക്വട്ടേഷൻ ട്രെൻഡുകൾ,
-Quoted Item Comparison,ഉദ്ധരിച്ച ഇനം താരതമ്യം,
 Received Items To Be Billed,ബില്ല് ലഭിച്ച ഇനങ്ങൾ,
 Qty to Order,ഓർഡർ Qty,
 Requested Items To Be Transferred,മാറ്റിയത് അഭ്യർത്ഥിച്ചു ഇനങ്ങൾ,
@@ -9834,3 +9832,9 @@
 Therapy Session overlaps with {0},തെറാപ്പി സെഷൻ {0 with ഓവർലാപ്പ് ചെയ്യുന്നു,
 Therapy Sessions Overlapping,തെറാപ്പി സെഷനുകൾ ഓവർലാപ്പുചെയ്യുന്നു,
 Therapy Plans,തെറാപ്പി പദ്ധതികൾ,
+"Item Code, warehouse, quantity are required on row {0}","Code 0 row വരിയിൽ ഇനം കോഡ്, വെയർഹ house സ്, അളവ് ആവശ്യമാണ്",
+Get Items from Material Requests against this Supplier,ഈ വിതരണക്കാരനെതിരായ മെറ്റീരിയൽ അഭ്യർത്ഥനകളിൽ നിന്ന് ഇനങ്ങൾ നേടുക,
+Enable European Access,യൂറോപ്യൻ ആക്സസ് പ്രാപ്തമാക്കുക,
+Creating Purchase Order ...,വാങ്ങൽ ഓർഡർ സൃഷ്ടിക്കുന്നു ...,
+"Select a Supplier from the Default Suppliers of the items below. On selection, a Purchase Order will be made against items belonging to the selected Supplier only.","ചുവടെയുള്ള ഇനങ്ങളുടെ സ്ഥിരസ്ഥിതി വിതരണക്കാരിൽ നിന്ന് ഒരു വിതരണക്കാരനെ തിരഞ്ഞെടുക്കുക. തിരഞ്ഞെടുക്കുമ്പോൾ, തിരഞ്ഞെടുത്ത വിതരണക്കാരന്റെ മാത്രം ഇനങ്ങൾക്കെതിരെ ഒരു വാങ്ങൽ ഓർഡർ നൽകും.",
+Row #{}: You must select {} serial numbers for item {}.,വരി # {}: നിങ്ങൾ item item ഇനത്തിനായി {} സീരിയൽ നമ്പറുകൾ തിരഞ്ഞെടുക്കണം.,
diff --git a/erpnext/translations/mr.csv b/erpnext/translations/mr.csv
index 1d63caf..9c41ce6 100644
--- a/erpnext/translations/mr.csv
+++ b/erpnext/translations/mr.csv
@@ -4238,7 +4238,6 @@
 End date can not be less than start date,समाप्ती तारीख प्रारंभ तारखेच्या पेक्षा कमी असू शकत नाही,
 For Default Supplier (Optional),डीफॉल्ट सप्लायर (वैकल्पिक) साठी,
 From date cannot be greater than To date,तारखेपासून तारखेपेक्षा जास्त असू शकत नाही,
-Get items from,आयटम मिळवा,
 Group by,गट,
 In stock,स्टॉक मध्ये,
 Item name,आयटम नाव,
@@ -8549,7 +8548,6 @@
 Purchase Receipt Trends,खरेदी पावती ट्रेन्ड,
 Purchase Register,खरेदी नोंदणी,
 Quotation Trends,कोटेशन ट्रेन्ड,
-Quoted Item Comparison,उद्धृत बाबींचा तुलना,
 Received Items To Be Billed,बिल करायचे प्राप्त आयटम,
 Qty to Order,मागणी करण्यासाठी  Qty,
 Requested Items To Be Transferred,विनंती आयटम हस्तांतरित करणे,
@@ -9834,3 +9832,9 @@
 Therapy Session overlaps with {0},थेरपी सत्र {0 with सह आच्छादित होते,
 Therapy Sessions Overlapping,थेरपी सत्रे आच्छादित,
 Therapy Plans,थेरपी योजना,
+"Item Code, warehouse, quantity are required on row {0}","पंक्तीवर आयटम कोड, कोठार, प्रमाण आवश्यक आहे {0}",
+Get Items from Material Requests against this Supplier,या पुरवठादाराविरूद्ध मटेरियल रिक्वेस्टचे आयटम मिळवा,
+Enable European Access,युरोपियन प्रवेश सक्षम करा,
+Creating Purchase Order ...,खरेदी ऑर्डर तयार करत आहे ...,
+"Select a Supplier from the Default Suppliers of the items below. On selection, a Purchase Order will be made against items belonging to the selected Supplier only.","खालील बाबींच्या डीफॉल्ट पुरवठादाराकडील पुरवठादार निवडा. निवडीवर, केवळ निवडलेल्या पुरवठादाराच्या वस्तूंच्या विरुद्ध खरेदी ऑर्डर देण्यात येईल.",
+Row #{}: You must select {} serial numbers for item {}.,पंक्ती # {}: आपण आयटम for for साठी} numbers अनुक्रमांक निवडणे आवश्यक आहे.,
diff --git a/erpnext/translations/ms.csv b/erpnext/translations/ms.csv
index 1d9aa75..1483844 100644
--- a/erpnext/translations/ms.csv
+++ b/erpnext/translations/ms.csv
@@ -4238,7 +4238,6 @@
 End date can not be less than start date,Tarikh akhir tidak boleh kurang daripada tarikh mula,
 For Default Supplier (Optional),Untuk pembekal lalai (pilihan),
 From date cannot be greater than To date,Dari Tarikh tidak boleh lebih besar daripada Dating,
-Get items from,Mendapatkan barangan dari,
 Group by,Group By,
 In stock,Dalam stok,
 Item name,Nama Item,
@@ -8549,7 +8548,6 @@
 Purchase Receipt Trends,Trend Resit Pembelian,
 Purchase Register,Pembelian Daftar,
 Quotation Trends,Trend Sebut Harga,
-Quoted Item Comparison,Perkara dipetik Perbandingan,
 Received Items To Be Billed,Barangan yang diterima dikenakan caj,
 Qty to Order,Qty Aturan,
 Requested Items To Be Transferred,Item yang diminta Akan Dipindahkan,
@@ -9834,3 +9832,9 @@
 Therapy Session overlaps with {0},Sesi Terapi bertindih dengan {0},
 Therapy Sessions Overlapping,Sesi Terapi Bertindih,
 Therapy Plans,Rancangan Terapi,
+"Item Code, warehouse, quantity are required on row {0}","Kod Item, gudang, kuantiti diperlukan pada baris {0}",
+Get Items from Material Requests against this Supplier,Dapatkan Item dari Permintaan Bahan terhadap Pembekal ini,
+Enable European Access,Dayakan Akses Eropah,
+Creating Purchase Order ...,Membuat Pesanan Pembelian ...,
+"Select a Supplier from the Default Suppliers of the items below. On selection, a Purchase Order will be made against items belonging to the selected Supplier only.","Pilih Pembekal dari Pembekal Lalai item di bawah. Pada pilihan, Pesanan Pembelian akan dibuat terhadap barang-barang milik Pembekal terpilih sahaja.",
+Row #{}: You must select {} serial numbers for item {}.,Baris # {}: Anda mesti memilih {} nombor siri untuk item {}.,
diff --git a/erpnext/translations/my.csv b/erpnext/translations/my.csv
index a505a5c..d15ec1e 100644
--- a/erpnext/translations/my.csv
+++ b/erpnext/translations/my.csv
@@ -4238,7 +4238,6 @@
 End date can not be less than start date,အဆုံးနေ့စွဲ Start ကိုနေ့စွဲထက်လျော့နည်းမဖွစျနိုငျ,
 For Default Supplier (Optional),ပုံမှန်ပေးသွင်း (ရွေးချယ်နိုင်),
 From date cannot be greater than To date,နေ့စွဲကနေနေ့စွဲရန်ထက် သာ. ကြီးမြတ်မဖွစျနိုငျ,
-Get items from,အထဲကပစ္စည်းတွေကို Get,
 Group by,Group မှဖြင့်,
 In stock,ကုန်ပစ္စည်းလက်ဝယ်ရှိ,
 Item name,item အမည်,
@@ -8549,7 +8548,6 @@
 Purchase Receipt Trends,ဝယ်ယူခြင်းပြေစာခေတ်ရေစီးကြောင်း,
 Purchase Register,မှတ်ပုံတင်မည်ဝယ်ယူ,
 Quotation Trends,စျေးနှုန်းခေတ်ရေစီးကြောင်း,
-Quoted Item Comparison,ကိုးကားအရာဝတ္ထုနှိုင်းယှဉ်ခြင်း,
 Received Items To Be Billed,ကြေညာတဲ့ခံရဖို့ရရှိထားသည့်ပစ္စည်းများ,
 Qty to Order,ရမလဲမှ Qty,
 Requested Items To Be Transferred,လွှဲပြောင်းရန်မေတ္တာရပ်ခံပစ္စည်းများ,
@@ -9834,3 +9832,9 @@
 Therapy Session overlaps with {0},ကုထုံးတွေ့ဆုံဆွေးနွေးမှု {0} နှင့်ထပ်နေသည်,
 Therapy Sessions Overlapping,ကုထုံးတွေ့ဆုံဆွေးနွေးပွဲ,
 Therapy Plans,ကုထုံးအစီအစဉ်များ,
+"Item Code, warehouse, quantity are required on row {0}","item ကုဒ်, ဂိုဒေါင်, အရေအတွက်အတန်း {0} တွင်လိုအပ်သည်။",
+Get Items from Material Requests against this Supplier,ဒီပေးသွင်းသူဆန့်ကျင်ပစ္စည်းတောင်းဆိုမှုများမှပစ္စည်းများရယူပါ,
+Enable European Access,ဥရောပ Access ကိုဖွင့်,
+Creating Purchase Order ...,ဝယ်ယူမှုအမိန့်ကိုဖန်တီးခြင်း ...,
+"Select a Supplier from the Default Suppliers of the items below. On selection, a Purchase Order will be made against items belonging to the selected Supplier only.",အောက်ဖော်ပြပါပစ္စည်းများ၏ပုံမှန်ပေးသွင်းသူထံမှပေးသွင်းရွေးချယ်ပါ။ ရွေးချယ်မှုတွင်ရွေးချယ်ထားသောပေးသွင်းသူနှင့်သာသက်ဆိုင်သောပစ္စည်းများကိုသာ ၀ ယ်ရန်အမိန့်ပေးလိမ့်မည်။,
+Row #{}: You must select {} serial numbers for item {}.,Row # {} - item {} အတွက်နံပါတ်စဉ်ဆက်ရွေးပါ။,
diff --git a/erpnext/translations/nl.csv b/erpnext/translations/nl.csv
index 33b1098..fbadc02 100644
--- a/erpnext/translations/nl.csv
+++ b/erpnext/translations/nl.csv
@@ -4238,7 +4238,6 @@
 End date can not be less than start date,Einddatum kan niet vroeger zijn dan startdatum,
 For Default Supplier (Optional),Voor standaardleverancier (optioneel),
 From date cannot be greater than To date,Vanaf de datum kan niet groter zijn dan tot nu toe,
-Get items from,Krijgen items uit,
 Group by,Groeperen volgens,
 In stock,Op voorraad,
 Item name,Artikelnaam,
@@ -8549,7 +8548,6 @@
 Purchase Receipt Trends,Ontvangstbevestiging Trends,
 Purchase Register,Inkoop Register,
 Quotation Trends,Offerte Trends,
-Quoted Item Comparison,Geciteerd Item Vergelijking,
 Received Items To Be Billed,Ontvangen artikelen nog te factureren,
 Qty to Order,Aantal te bestellen,
 Requested Items To Be Transferred,Aangevraagde Artikelen te Verplaatsen,
@@ -9834,3 +9832,9 @@
 Therapy Session overlaps with {0},Therapiesessie overlapt met {0},
 Therapy Sessions Overlapping,Therapiesessies overlappen elkaar,
 Therapy Plans,Therapieplannen,
+"Item Code, warehouse, quantity are required on row {0}","Artikelcode, magazijn, aantal zijn vereist op rij {0}",
+Get Items from Material Requests against this Supplier,Artikelen ophalen van materiaalverzoeken tegen deze leverancier,
+Enable European Access,Schakel Europese toegang in,
+Creating Purchase Order ...,Inkooporder creëren ...,
+"Select a Supplier from the Default Suppliers of the items below. On selection, a Purchase Order will be made against items belonging to the selected Supplier only.",Selecteer een leverancier uit de standaardleveranciers van de onderstaande items. Bij selectie wordt er alleen een inkooporder gemaakt voor artikelen van de geselecteerde leverancier.,
+Row #{}: You must select {} serial numbers for item {}.,Rij # {}: u moet {} serienummers voor artikel {} selecteren.,
diff --git a/erpnext/translations/no.csv b/erpnext/translations/no.csv
index bb8dbf2..150e5ca 100644
--- a/erpnext/translations/no.csv
+++ b/erpnext/translations/no.csv
@@ -4238,7 +4238,6 @@
 End date can not be less than start date,Sluttdato kan ikke være mindre enn startdato,
 For Default Supplier (Optional),For standardleverandør (valgfritt),
 From date cannot be greater than To date,Fra dato ikke kan være større enn To Date,
-Get items from,Få elementer fra,
 Group by,Grupper etter,
 In stock,På lager,
 Item name,Navn,
@@ -8549,7 +8548,6 @@
 Purchase Receipt Trends,Kvitteringen Trender,
 Purchase Register,Kjøp Register,
 Quotation Trends,Anførsels Trender,
-Quoted Item Comparison,Sitert Element Sammenligning,
 Received Items To Be Billed,Mottatte elementer å bli fakturert,
 Qty to Order,Antall å bestille,
 Requested Items To Be Transferred,Etterspør elementene som skal overføres,
@@ -9834,3 +9832,9 @@
 Therapy Session overlaps with {0},Behandlingsøkten overlapper med {0},
 Therapy Sessions Overlapping,Terapisessioner overlapper hverandre,
 Therapy Plans,Terapiplaner,
+"Item Code, warehouse, quantity are required on row {0}","Varekode, lager, antall kreves på rad {0}",
+Get Items from Material Requests against this Supplier,Få varer fra materialforespørsler mot denne leverandøren,
+Enable European Access,Aktiver europeisk tilgang,
+Creating Purchase Order ...,Opprette innkjøpsordre ...,
+"Select a Supplier from the Default Suppliers of the items below. On selection, a Purchase Order will be made against items belonging to the selected Supplier only.",Velg en leverandør fra standardleverandørene av artiklene nedenfor. Ved valg vil det kun gjøres en innkjøpsordre mot varer som tilhører den valgte leverandøren.,
+Row #{}: You must select {} serial numbers for item {}.,Rad nr. {}: Du må velge {} serienumre for varen {}.,
diff --git a/erpnext/translations/pl.csv b/erpnext/translations/pl.csv
index c30d055..8340b72 100644
--- a/erpnext/translations/pl.csv
+++ b/erpnext/translations/pl.csv
@@ -4238,7 +4238,6 @@
 End date can not be less than start date,"Data zakończenia nie może być wcześniejsza, niż data rozpoczęcia",
 For Default Supplier (Optional),Dla dostawcy domyślnego (opcjonalnie),
 From date cannot be greater than To date,Data od - nie może być późniejsza niż Data do,
-Get items from,Pobierz zawartość z,
 Group by,Grupuj według,
 In stock,W magazynie,
 Item name,Nazwa pozycji,
@@ -8549,7 +8548,6 @@
 Purchase Receipt Trends,Trendy Potwierdzenia Zakupu,
 Purchase Register,Rejestracja Zakupu,
 Quotation Trends,Trendy Wyceny,
-Quoted Item Comparison,Porównanie cytowany Item,
 Received Items To Be Billed,Otrzymane przedmioty czekające na zaksięgowanie,
 Qty to Order,Ilość do zamówienia,
 Requested Items To Be Transferred,Proszę o Przetranferowanie Przedmiotów,
@@ -9834,3 +9832,9 @@
 Therapy Session overlaps with {0},Sesja terapeutyczna pokrywa się z {0},
 Therapy Sessions Overlapping,Nakładanie się sesji terapeutycznych,
 Therapy Plans,Plany terapii,
+"Item Code, warehouse, quantity are required on row {0}","Kod pozycji, magazyn, ilość są wymagane w wierszu {0}",
+Get Items from Material Requests against this Supplier,Pobierz pozycje z żądań materiałowych od tego dostawcy,
+Enable European Access,Włącz dostęp w Europie,
+Creating Purchase Order ...,Tworzenie zamówienia zakupu ...,
+"Select a Supplier from the Default Suppliers of the items below. On selection, a Purchase Order will be made against items belonging to the selected Supplier only.","Wybierz dostawcę spośród domyślnych dostawców z poniższych pozycji. Po dokonaniu wyboru, Zamówienie zostanie złożone wyłącznie dla pozycji należących do wybranego Dostawcy.",
+Row #{}: You must select {} serial numbers for item {}.,Wiersz nr {}: należy wybrać {} numery seryjne dla towaru {}.,
diff --git a/erpnext/translations/ps.csv b/erpnext/translations/ps.csv
index d8a51ae..1dcaf48 100644
--- a/erpnext/translations/ps.csv
+++ b/erpnext/translations/ps.csv
@@ -4238,7 +4238,6 @@
 End date can not be less than start date,د پای نیټه نه شي کولای په پرتله د پیل نیټه کمه وي,
 For Default Supplier (Optional),د اصلي عرضه کوونکي لپاره (اختیاري),
 From date cannot be greater than To date,د نیټې څخه د نیټې څخه تر ډیره لوی نه وي,
-Get items from,له توکي ترلاسه کړئ,
 Group by,ډله په,
 In stock,په ګدام کښي,
 Item name,د قالب نوم,
@@ -8549,7 +8548,6 @@
 Purchase Receipt Trends,رانيول رسيد رجحانات,
 Purchase Register,رانيول د نوم ثبتول,
 Quotation Trends,د داوطلبۍ رجحانات,
-Quoted Item Comparison,له خولې د قالب پرتله,
 Received Items To Be Billed,ترلاسه توکي چې د محاسبې ته شي,
 Qty to Order,Qty ته اخلي.,
 Requested Items To Be Transferred,غوښتنه سامان ته انتقال شي,
@@ -9834,3 +9832,9 @@
 Therapy Session overlaps with {0},د درملنې ناسته د over 0 with سره پراخه کیږي,
 Therapy Sessions Overlapping,د تهيريپي ناستې پوړونه,
 Therapy Plans,د درملنې پلانونه,
+"Item Code, warehouse, quantity are required on row {0}",د توکي کوډ ، ګودام ، مقدار په قطار کې اړین دي {0},
+Get Items from Material Requests against this Supplier,د دې عرضه کونکي په وړاندې د موادو غوښتنو څخه توکي ترلاسه کړئ,
+Enable European Access,اروپایی لاسرسی وړ کړئ,
+Creating Purchase Order ...,د پیرود امر رامینځته کول ...,
+"Select a Supplier from the Default Suppliers of the items below. On selection, a Purchase Order will be made against items belonging to the selected Supplier only.",د لاندې شیانو ډیفالټ عرضه کونکو څخه یو عرضه کونکی غوره کړئ. په انتخاب کولو کې ، د پیرود امر به یوازې هغه انتخاب شوي چمتو کونکي پورې اړه لرونکي توکو په مقابل کې وي.,
+Row #{}: You must select {} serial numbers for item {}.,قطار # {}: تاسو باید د توکي {{لپاره سریال نمبرونه وټاکئ.,
diff --git a/erpnext/translations/pt.csv b/erpnext/translations/pt.csv
index 3289ef4..3b8a0a0 100644
--- a/erpnext/translations/pt.csv
+++ b/erpnext/translations/pt.csv
@@ -4238,7 +4238,6 @@
 End date can not be less than start date,A Data de Término não pode ser mais recente que a Data de Início,
 For Default Supplier (Optional),Para fornecedor padrão (opcional),
 From date cannot be greater than To date,De data não pode ser maior que a data,
-Get items from,Obter itens de,
 Group by,Agrupar Por,
 In stock,Em estoque,
 Item name,Nome do item,
@@ -8549,7 +8548,6 @@
 Purchase Receipt Trends,Tendências de Recibo de Compra,
 Purchase Register,Registo de Compra,
 Quotation Trends,Tendências de Cotação,
-Quoted Item Comparison,Comparação de Cotação de Item,
 Received Items To Be Billed,Itens Recebidos a Serem Faturados,
 Qty to Order,Qtd a Encomendar,
 Requested Items To Be Transferred,Itens Solicitados A Serem Transferidos,
@@ -9834,3 +9832,9 @@
 Therapy Session overlaps with {0},A sessão de terapia se sobrepõe a {0},
 Therapy Sessions Overlapping,Sobreposição de sessões de terapia,
 Therapy Plans,Planos de Terapia,
+"Item Code, warehouse, quantity are required on row {0}","Código do item, armazém, quantidade são necessários na linha {0}",
+Get Items from Material Requests against this Supplier,Obtenha itens de solicitações de materiais contra este fornecedor,
+Enable European Access,Habilitar acesso europeu,
+Creating Purchase Order ...,Criando pedido de compra ...,
+"Select a Supplier from the Default Suppliers of the items below. On selection, a Purchase Order will be made against items belonging to the selected Supplier only.","Selecione um fornecedor dos fornecedores padrão dos itens abaixo. Na seleção, um pedido de compra será feito apenas para itens pertencentes ao fornecedor selecionado.",
+Row #{}: You must select {} serial numbers for item {}.,Nº da linha {}: você deve selecionar {} números de série para o item {}.,
diff --git a/erpnext/translations/pt_br.csv b/erpnext/translations/pt_br.csv
index 620fe27..cda5ee8 100644
--- a/erpnext/translations/pt_br.csv
+++ b/erpnext/translations/pt_br.csv
@@ -985,6 +985,7 @@
 Qty,Qtde,
 Qty To Manufacture,Qtde para Fabricar,
 Qty for {0},Qtde para {0},
+Quality,QCคุณภาพ,
 Quality Goal.,Objetivos de Qualidade.,
 Quality Inspection,Inspeção de Qualidade,
 Quality Inspection: {0} is not submitted for the item: {1} in row {2},Inspeção de Qualidade: {0} não foi submetida para o item: {1} na linha {2},
diff --git a/erpnext/translations/ro.csv b/erpnext/translations/ro.csv
index 54211e2..643b8c5 100644
--- a/erpnext/translations/ro.csv
+++ b/erpnext/translations/ro.csv
@@ -4238,7 +4238,6 @@
 End date can not be less than start date,Data de Incheiere nu poate fi anterioara Datei de Incepere,
 For Default Supplier (Optional),Pentru furnizor implicit (opțional),
 From date cannot be greater than To date,De la data nu poate fi mai mare decât la data,
-Get items from,Obține elemente din,
 Group by,Grupul De,
 In stock,In stoc,
 Item name,Denumire Articol,
@@ -8549,7 +8548,6 @@
 Purchase Receipt Trends,Tendințe Primirea de cumpărare,
 Purchase Register,Cumpărare Inregistrare,
 Quotation Trends,Cotație Tendințe,
-Quoted Item Comparison,Compararea Articol citat,
 Received Items To Be Billed,Articole primite Pentru a fi facturat,
 Qty to Order,Cantitate pentru comandă,
 Requested Items To Be Transferred,Articole solicitate de transferat,
@@ -9834,3 +9832,9 @@
 Therapy Session overlaps with {0},Sesiunea de terapie se suprapune cu {0},
 Therapy Sessions Overlapping,Sesiunile de terapie se suprapun,
 Therapy Plans,Planuri de terapie,
+"Item Code, warehouse, quantity are required on row {0}","Codul articolului, depozitul, cantitatea sunt necesare pe rândul {0}",
+Get Items from Material Requests against this Supplier,Obțineți articole din solicitările materiale împotriva acestui furnizor,
+Enable European Access,Activați accesul european,
+Creating Purchase Order ...,Se creează comanda de cumpărare ...,
+"Select a Supplier from the Default Suppliers of the items below. On selection, a Purchase Order will be made against items belonging to the selected Supplier only.","Selectați un furnizor din furnizorii prestabiliți ai articolelor de mai jos. La selectare, o comandă de achiziție va fi făcută numai pentru articolele aparținând furnizorului selectat.",
+Row #{}: You must select {} serial numbers for item {}.,Rândul # {}: trebuie să selectați {} numere de serie pentru articol {}.,
diff --git a/erpnext/translations/ru.csv b/erpnext/translations/ru.csv
index 00a19b3..7fcb7b0 100644
--- a/erpnext/translations/ru.csv
+++ b/erpnext/translations/ru.csv
@@ -4238,7 +4238,6 @@
 End date can not be less than start date,"Дата окончания не может быть меньше, чем Дата начала",
 For Default Supplier (Optional),Поставщик по умолчанию (необязательно),
 From date cannot be greater than To date,"С даты не может быть больше, чем к дате",
-Get items from,Получить продукты от,
 Group by,Group By,
 In stock,В наличии,
 Item name,Название продукта,
@@ -8549,7 +8548,6 @@
 Purchase Receipt Trends,Динамика Получения Поставок,
 Purchase Register,Покупка Становиться на учет,
 Quotation Trends,Динамика предложений,
-Quoted Item Comparison,Цитируется Сравнение товара,
 Received Items To Be Billed,"Полученные товары, на которые нужно выписать счет",
 Qty to Order,Кол-во в заказ,
 Requested Items To Be Transferred,Запрашиваемые продукты к доставке,
@@ -9834,3 +9832,9 @@
 Therapy Session overlaps with {0},Сеанс терапии совпадает с {0},
 Therapy Sessions Overlapping,Совмещение сеансов терапии,
 Therapy Plans,Планы терапии,
+"Item Code, warehouse, quantity are required on row {0}","Код товара, склад, количество требуются в строке {0}",
+Get Items from Material Requests against this Supplier,Получить товары из запросов материалов к этому поставщику,
+Enable European Access,Включить европейский доступ,
+Creating Purchase Order ...,Создание заказа на поставку ...,
+"Select a Supplier from the Default Suppliers of the items below. On selection, a Purchase Order will be made against items belonging to the selected Supplier only.","Выберите поставщика из списка поставщиков по умолчанию для позиций ниже. При выборе Заказ на поставку будет сделан в отношении товаров, принадлежащих только выбранному Поставщику.",
+Row #{}: You must select {} serial numbers for item {}.,Строка № {}: необходимо выбрать {} серийных номеров для позиции {}.,
diff --git a/erpnext/translations/rw.csv b/erpnext/translations/rw.csv
index 5995db1..6459139 100644
--- a/erpnext/translations/rw.csv
+++ b/erpnext/translations/rw.csv
@@ -4238,7 +4238,6 @@
 End date can not be less than start date,Itariki yo kurangiriraho ntishobora kuba munsi yitariki yo gutangiriraho,
 For Default Supplier (Optional),Kubisanzwe Bitanga (Bihitamo),
 From date cannot be greater than To date,Kuva ku italiki ntishobora kurenza Kumunsi,
-Get items from,Shaka ibintu,
 Group by,Itsinda by,
 In stock,Mububiko,
 Item name,Izina ryikintu,
@@ -8549,7 +8548,6 @@
 Purchase Receipt Trends,Kugura inyemezabwishyu,
 Purchase Register,Kwiyandikisha,
 Quotation Trends,Imirongo,
-Quoted Item Comparison,Kugereranya Ikintu Kugereranya,
 Received Items To Be Billed,Yakiriye Ibintu Byishyurwa,
 Qty to Order,Qty gutumiza,
 Requested Items To Be Transferred,Ibintu Byasabwe Kwimurwa,
@@ -9834,3 +9832,9 @@
 Therapy Session overlaps with {0},Isomo ryo kuvura ryuzuzanya na {0},
 Therapy Sessions Overlapping,Amasomo yo kuvura,
 Therapy Plans,Gahunda yo kuvura,
+"Item Code, warehouse, quantity are required on row {0}","Kode yikintu, ububiko, ingano irakenewe kumurongo {0}",
+Get Items from Material Requests against this Supplier,Shakisha Ibintu Mubisabwa Ibikoresho Kurwanya Utanga isoko,
+Enable European Access,Gushoboza Uburayi,
+Creating Purchase Order ...,Gushiraho gahunda yo kugura ...,
+"Select a Supplier from the Default Suppliers of the items below. On selection, a Purchase Order will be made against items belonging to the selected Supplier only.","Hitamo Utanga isoko uhereye kubisanzwe bitanga ibintu hepfo. Muguhitamo, Iteka ryubuguzi rizakorwa kurwanya ibintu byatoranijwe gusa.",
+Row #{}: You must select {} serial numbers for item {}.,Umurongo # {}: Ugomba guhitamo {} nimero yuruhererekane kubintu {}.,
diff --git a/erpnext/translations/si.csv b/erpnext/translations/si.csv
index ba45b42..690c473 100644
--- a/erpnext/translations/si.csv
+++ b/erpnext/translations/si.csv
@@ -4238,7 +4238,6 @@
 End date can not be less than start date,අවසන් දිනය ඇරඹුම් දිනය ඊට වඩා අඩු විය නොහැක,
 For Default Supplier (Optional),Default සැපයුම්කරු සඳහා (විකල්ප),
 From date cannot be greater than To date,දිනය සිට දිනට වඩා වැඩි විය නොහැක,
-Get items from,සිට භාණ්ඩ ලබා ගන්න,
 Group by,කණ්ඩායම විසින්,
 In stock,ගබඩාවේ ඇත,
 Item name,අයිතමය නම,
@@ -8549,7 +8548,6 @@
 Purchase Receipt Trends,මිලදී ගැනීම රිසිට්පත ප්රවණතා,
 Purchase Register,මිලදී රෙජිස්ටර්,
 Quotation Trends,උද්ධෘත ප්රවණතා,
-Quoted Item Comparison,උපුටා අයිතමය සංසන්දනය,
 Received Items To Be Billed,ලැබී අයිතම බිල්පතක්,
 Qty to Order,ඇණවුම් යවන ලද,
 Requested Items To Be Transferred,ඉල්ලන අයිතම මාරු කර,
@@ -9834,3 +9832,9 @@
 Therapy Session overlaps with {0},චිකිත්සක සැසිය {0 with සමඟ අතිච්ඡාදනය වේ,
 Therapy Sessions Overlapping,චිකිත්සක සැසි අතිච්ඡාදනය,
 Therapy Plans,චිකිත්සක සැලසුම්,
+"Item Code, warehouse, quantity are required on row {0}","Code 0 row පේළියේ අයිතම කේතය, ගබඩාව, ප්‍රමාණය අවශ්‍ය වේ",
+Get Items from Material Requests against this Supplier,මෙම සැපයුම්කරුට එරෙහිව ද්‍රව්‍යමය ඉල්ලීම් වලින් අයිතම ලබා ගන්න,
+Enable European Access,යුරෝපීය ප්‍රවේශය සක්‍රීය කරන්න,
+Creating Purchase Order ...,මිලදී ගැනීමේ ඇණවුමක් නිර්මාණය කිරීම ...,
+"Select a Supplier from the Default Suppliers of the items below. On selection, a Purchase Order will be made against items belonging to the selected Supplier only.","පහත අයිතමවල පෙරනිමි සැපයුම්කරුවන්ගෙන් සැපයුම්කරුවෙකු තෝරන්න. තෝරාගැනීමේදී, තෝරාගත් සැපයුම්කරුට පමණක් අයත් භාණ්ඩවලට එරෙහිව මිලදී ගැනීමේ නියෝගයක් කරනු ලැබේ.",
+Row #{}: You must select {} serial numbers for item {}.,පේළිය # {}: ඔබ item item අයිතමය සඳහා {} අනුක්‍රමික අංක තෝරාගත යුතුය.,
diff --git a/erpnext/translations/sk.csv b/erpnext/translations/sk.csv
index d31adba..cb4a7fe 100644
--- a/erpnext/translations/sk.csv
+++ b/erpnext/translations/sk.csv
@@ -4238,7 +4238,6 @@
 End date can not be less than start date,Dátum ukončenia nemôže byť menší ako dátum začiatku,
 For Default Supplier (Optional),Pre predvoleného dodávateľa (nepovinné),
 From date cannot be greater than To date,Dátum OD nemôže byť väčší ako dátum DO,
-Get items from,Získať predmety z,
 Group by,Seskupit podle,
 In stock,Skladom,
 Item name,Názov položky,
@@ -8549,7 +8548,6 @@
 Purchase Receipt Trends,Doklad o koupi Trendy,
 Purchase Register,Nákup Register,
 Quotation Trends,Vývoje ponúk,
-Quoted Item Comparison,Citoval Položka Porovnanie,
 Received Items To Be Billed,"Přijaté položek, které mají být účtovány",
 Qty to Order,Množství k objednávce,
 Requested Items To Be Transferred,Požadované položky mají být převedeny,
@@ -9834,3 +9832,9 @@
 Therapy Session overlaps with {0},Terapeutické sedenie sa prekrýva s {0},
 Therapy Sessions Overlapping,Terapeutické sedenia sa prekrývajú,
 Therapy Plans,Terapeutické plány,
+"Item Code, warehouse, quantity are required on row {0}","V riadku {0} sa vyžaduje kód položky, sklad, množstvo",
+Get Items from Material Requests against this Supplier,Získajte položky z materiálových požiadaviek voči tomuto dodávateľovi,
+Enable European Access,Umožniť európsky prístup,
+Creating Purchase Order ...,Vytvára sa objednávka ...,
+"Select a Supplier from the Default Suppliers of the items below. On selection, a Purchase Order will be made against items belonging to the selected Supplier only.",Z predvolených dodávateľov nižšie uvedených položiek vyberte dodávateľa. Pri výbere sa uskutoční objednávka iba na položky patriace vybranému dodávateľovi.,
+Row #{}: You must select {} serial numbers for item {}.,Riadok č. {}: Musíte zvoliť {} sériové čísla pre položku {}.,
diff --git a/erpnext/translations/sl.csv b/erpnext/translations/sl.csv
index 15795dc..8beec6b 100644
--- a/erpnext/translations/sl.csv
+++ b/erpnext/translations/sl.csv
@@ -4238,7 +4238,6 @@
 End date can not be less than start date,Datum konca ne sme biti krajši od začetnega datuma,
 For Default Supplier (Optional),Za privzeto dobavitelja (neobvezno),
 From date cannot be greater than To date,Od datuma ne more biti večje od datuma,
-Get items from,Pridobi artikle iz,
 Group by,Skupina avtorja,
 In stock,Na zalogi,
 Item name,Ime predmeta,
@@ -8549,7 +8548,6 @@
 Purchase Receipt Trends,Nakup Prejem Trendi,
 Purchase Register,Nakup Register,
 Quotation Trends,Trendi ponudb,
-Quoted Item Comparison,Citirano Točka Primerjava,
 Received Items To Be Billed,Prejete Postavke placevali,
 Qty to Order,Količina naročiti,
 Requested Items To Be Transferred,Zahtevane blago prenaša,
@@ -9834,3 +9832,9 @@
 Therapy Session overlaps with {0},Seja terapije se prekriva z {0},
 Therapy Sessions Overlapping,Terapijske seje se prekrivajo,
 Therapy Plans,Načrti terapije,
+"Item Code, warehouse, quantity are required on row {0}","Koda artikla, skladišče, količina so obvezni v vrstici {0}",
+Get Items from Material Requests against this Supplier,Pridobite izdelke iz materialnih zahtevkov pri tem dobavitelju,
+Enable European Access,Omogoči evropski dostop,
+Creating Purchase Order ...,Ustvarjanje naročilnice ...,
+"Select a Supplier from the Default Suppliers of the items below. On selection, a Purchase Order will be made against items belonging to the selected Supplier only.","Izberite dobavitelja med privzetimi dobavitelji spodnjih elementov. Po izbiri bo naročilnica narejena samo za izdelke, ki pripadajo izbranemu dobavitelju.",
+Row #{}: You must select {} serial numbers for item {}.,Vrstica # {}: Izbrati morate {} serijske številke za izdelek {}.,
diff --git a/erpnext/translations/sq.csv b/erpnext/translations/sq.csv
index 18d634e..05aefa3 100644
--- a/erpnext/translations/sq.csv
+++ b/erpnext/translations/sq.csv
@@ -4238,7 +4238,6 @@
 End date can not be less than start date,Data e mbarimit nuk mund të jetë më e shkurtër se data fillestare,
 For Default Supplier (Optional),Për Furnizuesin e Parazgjedhur (fakultativ),
 From date cannot be greater than To date,Nga Data nuk mund të jetë më i madh se deri më sot,
-Get items from,Të marrë sendet nga,
 Group by,Grupi Nga,
 In stock,Në gjendje,
 Item name,Item Emri,
@@ -8549,7 +8548,6 @@
 Purchase Receipt Trends,Trendet Receipt Blerje,
 Purchase Register,Blerje Regjistrohu,
 Quotation Trends,Kuotimit Trendet,
-Quoted Item Comparison,Cituar Item Krahasimi,
 Received Items To Be Billed,Items marra Për të faturohet,
 Qty to Order,Qty të Rendit,
 Requested Items To Be Transferred,Items kërkuar të transferohet,
@@ -9834,3 +9832,9 @@
 Therapy Session overlaps with {0},Sesioni i terapisë mbivendoset me {0},
 Therapy Sessions Overlapping,Seancat e Terapisë Mbivendosen,
 Therapy Plans,Planet e Terapisë,
+"Item Code, warehouse, quantity are required on row {0}","Kodi i artikullit, depoja, sasia kërkohen në rreshtin {0}",
+Get Items from Material Requests against this Supplier,Merrni Artikuj nga Kërkesat Materiale kundër këtij Furnizuesi,
+Enable European Access,Aktivizo Aksesin Evropian,
+Creating Purchase Order ...,Krijimi i urdhrit të blerjes ...,
+"Select a Supplier from the Default Suppliers of the items below. On selection, a Purchase Order will be made against items belonging to the selected Supplier only.","Zgjidhni një furnitor nga furnitorët e parazgjedhur të artikujve më poshtë. Gjatë zgjedhjes, një Urdhër Blerje do të bëhet vetëm kundër artikujve që i përkasin vetëm Furnizuesit të zgjedhur.",
+Row #{}: You must select {} serial numbers for item {}.,Rreshti # {}: Duhet të zgjidhni {} numrat rendorë për artikullin {}.,
diff --git a/erpnext/translations/sr.csv b/erpnext/translations/sr.csv
index 44c4946..b507f74 100644
--- a/erpnext/translations/sr.csv
+++ b/erpnext/translations/sr.csv
@@ -4238,7 +4238,6 @@
 End date can not be less than start date,"Дата окончания не может быть меньше , чем Дата начала",
 For Default Supplier (Optional),За подразумевани добављач,
 From date cannot be greater than To date,Од датума не може бити већа него до сада,
-Get items from,Гет ставке из,
 Group by,Група По,
 In stock,На лагеру,
 Item name,Назив,
@@ -8549,7 +8548,6 @@
 Purchase Receipt Trends,Куповина Трендови Пријем,
 Purchase Register,Куповина Регистрација,
 Quotation Trends,Котировочные тенденции,
-Quoted Item Comparison,Цитирано артикла Поређење,
 Received Items To Be Billed,Примљени артикала буду наплаћени,
 Qty to Order,Количина по поруџбини,
 Requested Items To Be Transferred,Тражени Артикли ће се пренети,
@@ -9834,3 +9832,9 @@
 Therapy Session overlaps with {0},Сесија терапије се преклапа са {0},
 Therapy Sessions Overlapping,Преклапање сесија терапије,
 Therapy Plans,Планови терапије,
+"Item Code, warehouse, quantity are required on row {0}","Шифра артикла, складиште, количина су обавезни у реду {0}",
+Get Items from Material Requests against this Supplier,Узмите предмете од материјалних захтева против овог добављача,
+Enable European Access,Омогућити европски приступ,
+Creating Purchase Order ...,Креирање налога за куповину ...,
+"Select a Supplier from the Default Suppliers of the items below. On selection, a Purchase Order will be made against items belonging to the selected Supplier only.","Изаберите добављача од задатих добављача доле наведених ставки. Након одабира, наруџбеница ће се извршити само за производе који припадају изабраном добављачу.",
+Row #{}: You must select {} serial numbers for item {}.,Ред # {}: Морате одабрати {} серијске бројеве за ставку {}.,
diff --git a/erpnext/translations/sr_sp.csv b/erpnext/translations/sr_sp.csv
index 3304dfc..5e7ae79 100644
--- a/erpnext/translations/sr_sp.csv
+++ b/erpnext/translations/sr_sp.csv
@@ -649,7 +649,6 @@
 Yes,Da,
 Chart of Accounts,Kontni plan,
 Customer database.,Korisnička baza podataka,
-Get items from,Dodaj stavke iz,
 Item name,Naziv artikla,
 No employee found,Zaposleni nije pronađen,
 Open Projects ,Otvoreni projekti,
diff --git a/erpnext/translations/sv.csv b/erpnext/translations/sv.csv
index 608bb46..57e0279 100644
--- a/erpnext/translations/sv.csv
+++ b/erpnext/translations/sv.csv
@@ -4238,7 +4238,6 @@
 End date can not be less than start date,Slutdatum kan inte vara mindre än startdatum,
 For Default Supplier (Optional),För standardleverantör (tillval),
 From date cannot be greater than To date,Från datum kan inte vara större än till datum,
-Get items from,Få objekt från,
 Group by,Gruppera efter,
 In stock,I lager,
 Item name,Produktnamn,
@@ -8549,7 +8548,6 @@
 Purchase Receipt Trends,Kvitto Trender,
 Purchase Register,Inköpsregistret,
 Quotation Trends,Offert Trender,
-Quoted Item Comparison,Citerade föremål Jämförelse,
 Received Items To Be Billed,Mottagna objekt som ska faktureras,
 Qty to Order,Antal till Ordern,
 Requested Items To Be Transferred,Efterfrågade artiklar som ska överföras,
@@ -9834,3 +9832,9 @@
 Therapy Session overlaps with {0},Terapisessionen överlappar med {0},
 Therapy Sessions Overlapping,Terapisessioner överlappar varandra,
 Therapy Plans,Terapiplaner,
+"Item Code, warehouse, quantity are required on row {0}","Artikelkod, lager, kvantitet krävs på rad {0}",
+Get Items from Material Requests against this Supplier,Få objekt från materialförfrågningar mot denna leverantör,
+Enable European Access,Aktivera europeisk åtkomst,
+Creating Purchase Order ...,Skapar inköpsorder ...,
+"Select a Supplier from the Default Suppliers of the items below. On selection, a Purchase Order will be made against items belonging to the selected Supplier only.",Välj en leverantör bland standardleverantörerna av artiklarna nedan. Vid val kommer en inköpsorder endast göras mot föremål som tillhör vald leverantör.,
+Row #{}: You must select {} serial numbers for item {}.,Rad nr {}: Du måste välja {} serienummer för artikeln {}.,
diff --git a/erpnext/translations/sw.csv b/erpnext/translations/sw.csv
index bffc1a8..3595727 100644
--- a/erpnext/translations/sw.csv
+++ b/erpnext/translations/sw.csv
@@ -4238,7 +4238,6 @@
 End date can not be less than start date,Tarehe ya Mwisho haiwezi kuwa chini ya Tarehe ya Mwanzo,
 For Default Supplier (Optional),Kwa Default Supplier (hiari),
 From date cannot be greater than To date,Kutoka Tarehe haiwezi kuwa kubwa kuliko Tarehe,
-Get items from,Pata vitu kutoka,
 Group by,Kikundi Kwa,
 In stock,Katika hisa,
 Item name,Jina la Kipengee,
@@ -8549,7 +8548,6 @@
 Purchase Receipt Trends,Ununuzi Mwelekeo wa Receipt,
 Purchase Register,Daftari ya Ununuzi,
 Quotation Trends,Mwelekeo wa Nukuu,
-Quoted Item Comparison,Ilipendekeza Kulinganishwa kwa Bidhaa,
 Received Items To Be Billed,Vipokee Vipokee vya Kulipwa,
 Qty to Order,Uchina kwa Amri,
 Requested Items To Be Transferred,Vitu Vilivyoombwa Ili Kuhamishwa,
@@ -9834,3 +9832,9 @@
 Therapy Session overlaps with {0},Kipindi cha Tiba hupishana na {0},
 Therapy Sessions Overlapping,Vikao vya Tiba vinaingiliana,
 Therapy Plans,Mipango ya Tiba,
+"Item Code, warehouse, quantity are required on row {0}","Nambari ya Bidhaa, ghala, idadi inahitajika kwenye safu mlalo {0}",
+Get Items from Material Requests against this Supplier,Pata Vitu kutoka kwa Maombi ya Nyenzo dhidi ya Muuzaji huyu,
+Enable European Access,Washa Ufikiaji wa Uropa,
+Creating Purchase Order ...,Inaunda Agizo la Ununuzi ...,
+"Select a Supplier from the Default Suppliers of the items below. On selection, a Purchase Order will be made against items belonging to the selected Supplier only.","Chagua Muuzaji kutoka kwa Wasambazaji Default wa vitu hapa chini. Wakati wa kuchagua, Agizo la Ununuzi litafanywa dhidi ya vitu vya Muuzaji aliyechaguliwa tu.",
+Row #{}: You must select {} serial numbers for item {}.,Mstari # {}: Lazima uchague {} nambari za serial za kipengee {}.,
diff --git a/erpnext/translations/ta.csv b/erpnext/translations/ta.csv
index b57668d..100f0e9 100644
--- a/erpnext/translations/ta.csv
+++ b/erpnext/translations/ta.csv
@@ -4238,7 +4238,6 @@
 End date can not be less than start date,முடிவு தேதி தொடங்கும் நாள் விட குறைவாக இருக்க முடியாது,
 For Default Supplier (Optional),இயல்புநிலை வழங்குநருக்கு (விரும்பினால்),
 From date cannot be greater than To date,தேதி முதல் இன்று வரை விட முடியாது,
-Get items from,இருந்து பொருட்களை பெற,
 Group by,குழு மூலம்,
 In stock,கையிருப்பில்,
 Item name,பொருள் பெயர்,
@@ -8549,7 +8548,6 @@
 Purchase Receipt Trends,ரிசிப்ட் போக்குகள் வாங்குவதற்கு,
 Purchase Register,பதிவு வாங்குவதற்கு,
 Quotation Trends,மேற்கோள் போக்குகள்,
-Quoted Item Comparison,மேற்கோள் காட்டப்பட்டது பொருள் ஒப்பீட்டு,
 Received Items To Be Billed,கட்டணம் பெறப்படும் பொருட்கள்,
 Qty to Order,அளவு ஒழுங்கிற்கு,
 Requested Items To Be Transferred,மாற்றப்படுவதற்கு கோரப்பட்ட விடயங்கள்,
@@ -9834,3 +9832,9 @@
 Therapy Session overlaps with {0},சிகிச்சை அமர்வு {0 with உடன் ஒன்றுடன் ஒன்று,
 Therapy Sessions Overlapping,சிகிச்சை அமர்வுகள் ஒன்றுடன் ஒன்று,
 Therapy Plans,சிகிச்சை திட்டங்கள்,
+"Item Code, warehouse, quantity are required on row {0}","Code 0 row வரிசையில் உருப்படி குறியீடு, கிடங்கு, அளவு தேவை",
+Get Items from Material Requests against this Supplier,இந்த சப்ளையருக்கு எதிரான பொருள் கோரிக்கைகளிலிருந்து பொருட்களைப் பெறுங்கள்,
+Enable European Access,ஐரோப்பிய அணுகலை இயக்கு,
+Creating Purchase Order ...,கொள்முதல் ஆணையை உருவாக்குதல் ...,
+"Select a Supplier from the Default Suppliers of the items below. On selection, a Purchase Order will be made against items belonging to the selected Supplier only.","கீழே உள்ள பொருட்களின் இயல்புநிலை சப்ளையர்களிடமிருந்து ஒரு சப்ளையரைத் தேர்ந்தெடுக்கவும். தேர்ந்தெடுக்கும் போது, தேர்ந்தெடுக்கப்பட்ட சப்ளையருக்கு மட்டுமே சொந்தமான பொருட்களுக்கு எதிராக கொள்முதல் ஆணை செய்யப்படும்.",
+Row #{}: You must select {} serial numbers for item {}.,வரிசை # {}: நீங்கள் item item உருப்படிக்கு {} வரிசை எண்களைத் தேர்ந்தெடுக்க வேண்டும்.,
diff --git a/erpnext/translations/te.csv b/erpnext/translations/te.csv
index e5ba32c..047d077 100644
--- a/erpnext/translations/te.csv
+++ b/erpnext/translations/te.csv
@@ -4238,7 +4238,6 @@
 End date can not be less than start date,ముగింపు తేదీ ప్రారంభ తేదీ కంటే తక్కువ ఉండకూడదు,
 For Default Supplier (Optional),డిఫాల్ట్ సరఫరాదారు (ఐచ్ఛిక) కోసం,
 From date cannot be greater than To date,తేదీ నుండి తేదీ వరకు ఎక్కువ ఉండకూడదు,
-Get items from,నుండి అంశాలను పొందండి,
 Group by,గ్రూప్ ద్వారా,
 In stock,అందుబాటులో ఉంది,
 Item name,అంశం పేరు,
@@ -8549,7 +8548,6 @@
 Purchase Receipt Trends,కొనుగోలు రసీదులు ట్రెండ్లులో,
 Purchase Register,కొనుగోలు నమోదు,
 Quotation Trends,కొటేషన్ ట్రెండ్లులో,
-Quoted Item Comparison,ఉల్లేఖించిన అంశం పోలిక,
 Received Items To Be Billed,స్వీకరించిన అంశాలు బిల్ టు,
 Qty to Order,ఆర్డర్ చేయటం అంశాల,
 Requested Items To Be Transferred,అభ్యర్థించిన అంశాలు బదిలీ,
@@ -9834,3 +9832,9 @@
 Therapy Session overlaps with {0},థెరపీ సెషన్ {0 with తో అతివ్యాప్తి చెందుతుంది,
 Therapy Sessions Overlapping,థెరపీ సెషన్స్ అతివ్యాప్తి,
 Therapy Plans,చికిత్స ప్రణాళికలు,
+"Item Code, warehouse, quantity are required on row {0}","Code 0 row వరుసలో అంశం కోడ్, గిడ్డంగి, పరిమాణం అవసరం",
+Get Items from Material Requests against this Supplier,ఈ సరఫరాదారుకు వ్యతిరేకంగా మెటీరియల్ అభ్యర్థనల నుండి అంశాలను పొందండి,
+Enable European Access,యూరోపియన్ ప్రాప్యతను ప్రారంభించండి,
+Creating Purchase Order ...,కొనుగోలు క్రమాన్ని సృష్టిస్తోంది ...,
+"Select a Supplier from the Default Suppliers of the items below. On selection, a Purchase Order will be made against items belonging to the selected Supplier only.","దిగువ వస్తువుల డిఫాల్ట్ సరఫరాదారుల నుండి సరఫరాదారుని ఎంచుకోండి. ఎంపికపై, ఎంచుకున్న సరఫరాదారుకు చెందిన వస్తువులపై మాత్రమే కొనుగోలు ఆర్డర్ చేయబడుతుంది.",
+Row #{}: You must select {} serial numbers for item {}.,అడ్డు వరుస # {}: మీరు తప్పక item} అంశం కోసం {} క్రమ సంఖ్యలను ఎంచుకోవాలి.,
diff --git a/erpnext/translations/th.csv b/erpnext/translations/th.csv
index 90c3a9a..71233ec 100644
--- a/erpnext/translations/th.csv
+++ b/erpnext/translations/th.csv
@@ -4238,7 +4238,6 @@
 End date can not be less than start date,วันที่สิ้นสุด ไม่สามารถ จะน้อยกว่า วันเริ่มต้น,
 For Default Supplier (Optional),สำหรับผู้จัดจำหน่ายเริ่มต้น (ตัวเลือก),
 From date cannot be greater than To date,จากวันที่ไม่สามารถมากกว่าวันที่,
-Get items from,รับรายการจาก,
 Group by,กลุ่มตาม,
 In stock,มีสินค้าในสต๊อก,
 Item name,ชื่อรายการ,
@@ -8549,7 +8548,6 @@
 Purchase Receipt Trends,ซื้อแนวโน้มใบเสร็จรับเงิน,
 Purchase Register,สั่งซื้อสมัครสมาชิก,
 Quotation Trends,ใบเสนอราคา แนวโน้ม,
-Quoted Item Comparison,เปรียบเทียบรายการที่ยกมา,
 Received Items To Be Billed,รายการที่ได้รับจะถูกเรียกเก็บเงิน,
 Qty to Order,จำนวนการสั่งซื้อสินค้า,
 Requested Items To Be Transferred,รายการที่ได้รับการร้องขอจะถูกถ่ายโอน,
@@ -9834,3 +9832,9 @@
 Therapy Session overlaps with {0},เซสชันการบำบัดทับซ้อนกับ {0},
 Therapy Sessions Overlapping,การบำบัดที่ทับซ้อนกัน,
 Therapy Plans,แผนการบำบัด,
+"Item Code, warehouse, quantity are required on row {0}",ต้องระบุรหัสสินค้าคลังสินค้าปริมาณในแถว {0},
+Get Items from Material Requests against this Supplier,รับรายการจากคำขอวัสดุกับซัพพลายเออร์นี้,
+Enable European Access,เปิดใช้งาน European Access,
+Creating Purchase Order ...,กำลังสร้างใบสั่งซื้อ ...,
+"Select a Supplier from the Default Suppliers of the items below. On selection, a Purchase Order will be made against items belonging to the selected Supplier only.",เลือกซัพพลายเออร์จากซัพพลายเออร์เริ่มต้นของรายการด้านล่าง ในการเลือกใบสั่งซื้อจะทำกับสินค้าที่เป็นของซัพพลายเออร์ที่เลือกเท่านั้น,
+Row #{}: You must select {} serial numbers for item {}.,แถว # {}: คุณต้องเลือก {} หมายเลขซีเรียลสำหรับรายการ {},
diff --git a/erpnext/translations/tr.csv b/erpnext/translations/tr.csv
index ebb754a..9e7ba4d 100644
--- a/erpnext/translations/tr.csv
+++ b/erpnext/translations/tr.csv
@@ -4238,7 +4238,6 @@
 End date can not be less than start date,"Bitiş Tarihi, Başlangıç Tarihinden daha az olamaz",
 For Default Supplier (Optional),Varsayılan Tedarikçi için (İsteğe bağlı),
 From date cannot be greater than To date,Tarihten itibaren tarihe kadardan ileride olamaz,
-Get items from,Öğeleri alın,
 Group by,Grup tarafından,
 In stock,Stokta var,
 Item name,Ürün Adı,
@@ -8549,7 +8548,6 @@
 Purchase Receipt Trends,Satın Alma Teslim Alma Analizi,
 Purchase Register,Satın alma kaydı,
 Quotation Trends,Teklif Trendleri,
-Quoted Item Comparison,Kote Ürün Karşılaştırma,
 Received Items To Be Billed,Faturalanacak  Alınan Malzemeler,
 Qty to Order,Sipariş Miktarı,
 Requested Items To Be Transferred,Transfer edilmesi istenen Ürünler,
@@ -9834,3 +9832,9 @@
 Therapy Session overlaps with {0},"Terapi Oturumu, {0} ile çakışıyor",
 Therapy Sessions Overlapping,Çakışan Terapi Seansları,
 Therapy Plans,Tedavi Planları,
+"Item Code, warehouse, quantity are required on row {0}","{0}. Satırda Öğe Kodu, depo, miktar gerekli",
+Get Items from Material Requests against this Supplier,Bu Tedarikçiye Karşı Malzeme Taleplerinden Ürün Alın,
+Enable European Access,Avrupa Erişimini Etkinleştir,
+Creating Purchase Order ...,Satın Alma Siparişi Oluşturuluyor ...,
+"Select a Supplier from the Default Suppliers of the items below. On selection, a Purchase Order will be made against items belonging to the selected Supplier only.","Aşağıdaki öğelerin Varsayılan Tedarikçilerinden bir Tedarikçi seçin. Seçim üzerine, yalnızca seçilen Tedarikçiye ait ürünler için bir Satın Alma Siparişi verilecektir.",
+Row #{}: You must select {} serial numbers for item {}.,Satır # {}: {} öğesi için {} seri numaralarını seçmelisiniz.,
diff --git a/erpnext/translations/uk.csv b/erpnext/translations/uk.csv
index b43346c..53e2df5 100644
--- a/erpnext/translations/uk.csv
+++ b/erpnext/translations/uk.csv
@@ -4238,7 +4238,6 @@
 End date can not be less than start date,"Дата завершення не може бути меншою, ніж Дата початку",
 For Default Supplier (Optional),Для постачальника за замовчуванням (необов&#39;язково),
 From date cannot be greater than To date,"Від дати не може бути більше, ніж Дата",
-Get items from,Отримати елементи з,
 Group by,Групувати за,
 In stock,В наявності,
 Item name,Назва виробу,
@@ -8549,7 +8548,6 @@
 Purchase Receipt Trends,Тренд прихідних накладних,
 Purchase Register,Реєстр закупівель,
 Quotation Trends,Тренд пропозицій,
-Quoted Item Comparison,Цитується Порівняння товару,
 Received Items To Be Billed,"Отримані позиції, на які не виставлені рахунки",
 Qty to Order,К-сть для замовлення,
 Requested Items To Be Transferred,"Номенклатура, що ми замовили але не отримали",
@@ -9834,3 +9832,9 @@
 Therapy Session overlaps with {0},Сеанс терапії накладається на {0},
 Therapy Sessions Overlapping,"Сеанси терапії, що перекриваються",
 Therapy Plans,Плани терапії,
+"Item Code, warehouse, quantity are required on row {0}","Код товару, склад, кількість вказуються в рядку {0}",
+Get Items from Material Requests against this Supplier,Отримуйте предмети від матеріальних запитів у цього постачальника,
+Enable European Access,Увімкнути європейський доступ,
+Creating Purchase Order ...,Створення замовлення на придбання ...,
+"Select a Supplier from the Default Suppliers of the items below. On selection, a Purchase Order will be made against items belonging to the selected Supplier only.","Виберіть постачальника з постачальників за замовчуванням із наведених нижче пунктів. При виборі замовлення на замовлення буде зроблено лише щодо товарів, що належать обраному Постачальнику.",
+Row #{}: You must select {} serial numbers for item {}.,Рядок № {}: Ви повинні вибрати {} серійні номери для товару {}.,
diff --git a/erpnext/translations/ur.csv b/erpnext/translations/ur.csv
index 7d9cacd..aaaef58 100644
--- a/erpnext/translations/ur.csv
+++ b/erpnext/translations/ur.csv
@@ -4238,7 +4238,6 @@
 End date can not be less than start date,ختم ہونے کی تاریخ شروع کرنے کی تاریخ کے مقابلے میں کم نہیں ہو سکتا,
 For Default Supplier (Optional),ڈیفالٹ سپلائر کے لئے (اختیاری),
 From date cannot be greater than To date,تاریخ سے تاریخ سے زیادہ نہیں ہوسکتی ہے,
-Get items from,سے اشیاء حاصل,
 Group by,گروپ سے,
 In stock,اسٹاک میں,
 Item name,نام شے,
@@ -8549,7 +8548,6 @@
 Purchase Receipt Trends,خریداری کی رسید رجحانات,
 Purchase Register,خریداری رجسٹر,
 Quotation Trends,کوٹیشن رجحانات,
-Quoted Item Comparison,نقل آئٹم موازنہ,
 Received Items To Be Billed,موصول ہونے والی اشیاء بل بھیجا جائے کرنے کے لئے,
 Qty to Order,آرڈر کی مقدار,
 Requested Items To Be Transferred,درخواست کی اشیاء منتقل کیا جائے,
@@ -9834,3 +9832,9 @@
 Therapy Session overlaps with {0},تھراپی سیشن {0 with کے ساتھ اوورلیپ ہوتا ہے,
 Therapy Sessions Overlapping,تھراپی سیشن اوور لیپنگ,
 Therapy Plans,تھراپی کے منصوبے,
+"Item Code, warehouse, quantity are required on row {0}",آئٹم کوڈ ، گودام ، مقدار قطار میں ضروری ہے {0},
+Get Items from Material Requests against this Supplier,اس سپلائر کے خلاف مادی درخواستوں سے اشیا حاصل کریں,
+Enable European Access,یورپی رسائی کو فعال کریں,
+Creating Purchase Order ...,خریداری کا آرڈر تشکیل دے رہا ہے…,
+"Select a Supplier from the Default Suppliers of the items below. On selection, a Purchase Order will be made against items belonging to the selected Supplier only.",ذیل میں آئٹمز کے ڈیفالٹ سپلائرز میں سے ایک سپلائر منتخب کریں۔ انتخاب پر ، خریداری کا آرڈر صرف منتخب کردہ سپلائر سے متعلقہ اشیاء کے خلاف کیا جائے گا۔,
+Row #{}: You must select {} serial numbers for item {}.,قطار # {}: آپ کو آئٹم for for کے لئے}} سیریل نمبرز منتخب کرنا ہوں گے۔,
diff --git a/erpnext/translations/uz.csv b/erpnext/translations/uz.csv
index f05b582..c983797 100644
--- a/erpnext/translations/uz.csv
+++ b/erpnext/translations/uz.csv
@@ -4238,7 +4238,6 @@
 End date can not be less than start date,Tugash sanasi Boshlanish sanasidan past bo&#39;lishi mumkin emas,
 For Default Supplier (Optional),Standart yetkazib beruvchi (ixtiyoriy),
 From date cannot be greater than To date,Sana Sana Sana uchun katta bo&#39;lishi mumkin emas,
-Get items from,Elementlarni oling,
 Group by,Guruh tomonidan,
 In stock,Omborda mavjud; sotuvda mavjud,
 Item name,Mavzu nomi,
@@ -8549,7 +8548,6 @@
 Purchase Receipt Trends,Qabul rejasi xaridlari,
 Purchase Register,Xarid qilish Register,
 Quotation Trends,Iqtiboslar tendentsiyalari,
-Quoted Item Comparison,Qisqartirilgan ob&#39;ektni solishtirish,
 Received Items To Be Billed,Qabul qilinadigan buyumlar,
 Qty to Order,Buyurtma miqdori,
 Requested Items To Be Transferred,Talab qilingan narsalarni yuborish,
@@ -9834,3 +9832,9 @@
 Therapy Session overlaps with {0},Terapiya mashg&#39;uloti {0} bilan takrorlanadi,
 Therapy Sessions Overlapping,Terapiya mashg&#39;ulotlari bir-birini qoplaydi,
 Therapy Plans,Terapiya rejalari,
+"Item Code, warehouse, quantity are required on row {0}","Mahsulot kodi, ombor, miqdori {0} qatorida talab qilinadi",
+Get Items from Material Requests against this Supplier,Ushbu etkazib beruvchiga qarshi material talablaridan narsalarni oling,
+Enable European Access,Evropaga kirishni yoqish,
+Creating Purchase Order ...,Xarid buyurtmasi yaratilmoqda ...,
+"Select a Supplier from the Default Suppliers of the items below. On selection, a Purchase Order will be made against items belonging to the selected Supplier only.","Quyidagi mahsulotlarning standart etkazib beruvchilardan etkazib beruvchini tanlang. Tanlovda, faqat tanlangan etkazib beruvchiga tegishli buyumlarga qarshi Sotib olish to&#39;g&#39;risida buyurtma beriladi.",
+Row #{}: You must select {} serial numbers for item {}.,Qator # {}: Siz {} element uchun seriya raqamlarini {} tanlashingiz kerak.,
diff --git a/erpnext/translations/vi.csv b/erpnext/translations/vi.csv
index a76c9fd..03ff2cc 100644
--- a/erpnext/translations/vi.csv
+++ b/erpnext/translations/vi.csv
@@ -4238,7 +4238,6 @@
 End date can not be less than start date,Ngày kết thúc không thể nhỏ hơn Bắt đầu ngày,
 For Default Supplier (Optional),Đối với nhà cung cấp mặc định (Tùy chọn),
 From date cannot be greater than To date,"""Từ ngày"" không có thể lớn hơn ""Đến ngày""",
-Get items from,Lấy dữ liệu từ,
 Group by,Nhóm theo,
 In stock,Trong kho,
 Item name,Tên hàng,
@@ -8549,7 +8548,6 @@
 Purchase Receipt Trends,Xu hướng của biên lai nhận hàng,
 Purchase Register,Đăng ký mua,
 Quotation Trends,Các Xu hướng dự kê giá,
-Quoted Item Comparison,So sánh mẫu hàng đã được báo giá,
 Received Items To Be Billed,Những mẫu hàng nhận được để lập hóa đơn,
 Qty to Order,Số lượng đặt hàng,
 Requested Items To Be Transferred,Mục yêu cầu được chuyển giao,
@@ -9834,3 +9832,9 @@
 Therapy Session overlaps with {0},Phiên trị liệu trùng lặp với {0},
 Therapy Sessions Overlapping,Các phiên trị liệu chồng chéo,
 Therapy Plans,Kế hoạch trị liệu,
+"Item Code, warehouse, quantity are required on row {0}","Mã hàng, kho, số lượng là bắt buộc trên hàng {0}",
+Get Items from Material Requests against this Supplier,Nhận các mặt hàng từ các Yêu cầu Vật liệu đối với Nhà cung cấp này,
+Enable European Access,Bật quyền truy cập Châu Âu,
+Creating Purchase Order ...,Tạo Đơn đặt hàng ...,
+"Select a Supplier from the Default Suppliers of the items below. On selection, a Purchase Order will be made against items belonging to the selected Supplier only.","Chọn Nhà cung cấp từ các Nhà cung cấp mặc định của các mục dưới đây. Khi lựa chọn, Đơn đặt hàng sẽ được thực hiện đối với các mặt hàng chỉ thuộc về Nhà cung cấp đã chọn.",
+Row #{}: You must select {} serial numbers for item {}.,Hàng # {}: Bạn phải chọn {} số sê-ri cho mặt hàng {}.,
diff --git a/erpnext/translations/zh.csv b/erpnext/translations/zh.csv
index 97c69fe..716f1f2 100644
--- a/erpnext/translations/zh.csv
+++ b/erpnext/translations/zh.csv
@@ -4238,7 +4238,6 @@
 End date can not be less than start date,结束日期不能小于开始日期,
 For Default Supplier (Optional),对于默认供应商(可选),
 From date cannot be greater than To date,从日期不能大于到日期,
-Get items from,从...获取物料,
 Group by,分组基于,
 In stock,有现货,
 Item name,物料名称,
@@ -8549,7 +8548,6 @@
 Purchase Receipt Trends,采购收货趋势,
 Purchase Register,采购台帐,
 Quotation Trends,报价趋势,
-Quoted Item Comparison,项目报价比较,
 Received Items To Be Billed,待开费用清单已收货物料,
 Qty to Order,待下单数量,
 Requested Items To Be Transferred,已申请待移转物料,
@@ -9834,3 +9832,9 @@
 Therapy Session overlaps with {0},治疗会话与{0}重叠,
 Therapy Sessions Overlapping,治疗会议重叠,
 Therapy Plans,治疗计划,
+"Item Code, warehouse, quantity are required on row {0}",在第{0}行中需要提供物料代码,仓库,数量,
+Get Items from Material Requests against this Supplier,从针对此供应商的物料请求中获取物料,
+Enable European Access,启用欧洲访问,
+Creating Purchase Order ...,创建采购订单...,
+"Select a Supplier from the Default Suppliers of the items below. On selection, a Purchase Order will be made against items belonging to the selected Supplier only.",从以下各项的默认供应商中选择供应商。选择后,将针对仅属于所选供应商的项目下达采购订单。,
+Row #{}: You must select {} serial numbers for item {}.,行号{}:您必须为项目{}选择{}序列号。,
diff --git a/erpnext/translations/zh_tw.csv b/erpnext/translations/zh_tw.csv
index 2de0df0..1cc7d87 100644
--- a/erpnext/translations/zh_tw.csv
+++ b/erpnext/translations/zh_tw.csv
@@ -3967,7 +3967,6 @@
 End date can not be less than start date,結束日期不能小於開始日期,
 For Default Supplier (Optional),對於默認供應商(可選),
 From date cannot be greater than To date,起始日期不能大於結束日期,
-Get items from,取得項目來源,
 Group by,集團通過,
 In stock,有現貨,
 Item name,項目名稱,
@@ -7967,7 +7966,6 @@
 Purchase Receipt Trends,採購入庫趨勢,
 Purchase Register,購買註冊,
 Quotation Trends,報價趨勢,
-Quoted Item Comparison,項目報價比較,
 Received Items To Be Billed,待付款的收受品項,
 Qty to Order,訂購數量,
 Requested Items To Be Transferred,將要轉倉的需求項目,
@@ -9136,3 +9134,9 @@
 Therapy Session overlaps with {0},治療會話與{0}重疊,
 Therapy Sessions Overlapping,治療會議重疊,
 Therapy Plans,治療計劃,
+"Item Code, warehouse, quantity are required on row {0}",在第{0}行中需要提供物料代碼,倉庫,數量,
+Get Items from Material Requests against this Supplier,從針對此供應商的物料請求中獲取物料,
+Enable European Access,啟用歐洲訪問,
+Creating Purchase Order ...,創建採購訂單...,
+"Select a Supplier from the Default Suppliers of the items below. On selection, a Purchase Order will be made against items belonging to the selected Supplier only.",從以下各項的默認供應商中選擇供應商。選擇後,將針對僅屬於所選供應商的項目下達採購訂單。,
+Row #{}: You must select {} serial numbers for item {}.,行號{}:您必須為項目{}選擇{}序列號。,