Merge pull request #24745 from ankush/no_team_updates

fix(HR): hide "more" button from team updates
diff --git a/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.py b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.py
index 1bd42f5..0ebf0eb 100644
--- a/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.py
+++ b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.py
@@ -61,8 +61,10 @@
 	def on_update(self):
 		frappe.flags.accounting_dimensions = None
 
-def make_dimension_in_accounting_doctypes(doc):
-	doclist = get_doctypes_with_dimensions()
+def make_dimension_in_accounting_doctypes(doc, doclist=None):
+	if not doclist:
+		doclist = get_doctypes_with_dimensions()
+
 	doc_count = len(get_accounting_dimensions())
 	count = 0
 
@@ -82,13 +84,13 @@
 			"owner": "Administrator"
 		}
 
-		if doctype == "Budget":
-			add_dimension_to_budget_doctype(df, doc)
-		else:
-			meta = frappe.get_meta(doctype, cached=False)
-			fieldnames = [d.fieldname for d in meta.get("fields")]
+		meta = frappe.get_meta(doctype, cached=False)
+		fieldnames = [d.fieldname for d in meta.get("fields")]
 
-			if df['fieldname'] not in fieldnames:
+		if df['fieldname'] not in fieldnames:
+			if doctype == "Budget":
+				add_dimension_to_budget_doctype(df.copy(), doc)
+			else:
 				create_custom_field(doctype, df)
 
 		count += 1
@@ -178,15 +180,7 @@
 		frappe.clear_cache(doctype=doctype)
 
 def get_doctypes_with_dimensions():
-	doclist = ["GL Entry", "Sales Invoice", "POS Invoice", "Purchase Invoice", "Payment Entry", "Asset",
-		"Expense Claim", "Expense Claim Detail", "Expense Taxes and Charges", "Stock Entry", "Budget", "Payroll Entry", "Delivery Note",
-		"Sales Invoice Item", "POS Invoice Item", "Purchase Invoice Item", "Purchase Order Item", "Journal Entry Account", "Material Request Item", "Delivery Note Item",
-		"Purchase Receipt Item", "Stock Entry Detail", "Payment Entry Deduction", "Sales Taxes and Charges", "Purchase Taxes and Charges", "Shipping Rule",
-		"Landed Cost Item", "Asset Value Adjustment", "Loyalty Program", "Fee Schedule", "Fee Structure", "Stock Reconciliation",
-		"Travel Request", "Fees", "POS Profile", "Opening Invoice Creation Tool", "Opening Invoice Creation Tool Item", "Subscription",
-		"Subscription Plan"]
-
-	return doclist
+	return frappe.get_hooks("accounting_dimension_doctypes")
 
 def get_accounting_dimensions(as_list=True):
 	if frappe.flags.accounting_dimensions is None:
diff --git a/erpnext/accounts/doctype/chart_of_accounts_importer/chart_of_accounts_importer.py b/erpnext/accounts/doctype/chart_of_accounts_importer/chart_of_accounts_importer.py
index 342f21b..03c3eb0 100644
--- a/erpnext/accounts/doctype/chart_of_accounts_importer/chart_of_accounts_importer.py
+++ b/erpnext/accounts/doctype/chart_of_accounts_importer/chart_of_accounts_importer.py
@@ -22,9 +22,10 @@
 		'allow_account_creation_against_child_company'])
 
 	if parent_company and (not allow_account_creation_against_child_company):
-		frappe.throw(_("""{0} is a child company. Please import accounts against parent company
-			or enable {1} in company master""").format(frappe.bold(company),
-			frappe.bold('Allow Account Creation Against Child Company')), title='Wrong Company')
+		msg = _("{} is a child company. ").format(frappe.bold(company))
+		msg += _("Please import accounts against parent company or enable {} in company master.").format(
+			frappe.bold('Allow Account Creation Against Child Company'))
+		frappe.throw(msg, title=_('Wrong Company'))
 
 	if frappe.db.get_all('GL Entry', {"company": company}, "name", limit=1):
 		return False
@@ -74,7 +75,9 @@
 			if as_dict:
 				data.append({frappe.scrub(header): row[index] for index, header in enumerate(headers)})
 			else:
-				if not row[1]: row[1] = row[0]
+				if not row[1]:
+					row[1] = row[0]
+					row[3] = row[2]
 				data.append(row)
 
 	# convert csv data
@@ -96,7 +99,9 @@
 		if as_dict:
 			data.append({frappe.scrub(header): row[index] for index, header in enumerate(headers)})
 		else:
-			if not row[1]: row[1] = row[0]
+			if not row[1]:
+					row[1] = row[0]
+					row[3] = row[2]
 			data.append(row)
 
 	return data
@@ -147,7 +152,13 @@
 		from frappe import _
 
 		for row in data:
-			account_name, parent_account = row[0:2]
+			account_name, parent_account, account_number, parent_account_number = row[0:4]
+			if account_number:
+				account_name = "{} - {}".format(account_number, account_name)
+			if parent_account_number:
+				parent_account_number = cstr(parent_account_number).strip()
+				parent_account = "{} - {}".format(parent_account_number, parent_account)
+
 			if parent_account == account_name == child:
 				return [parent_account]
 			elif account_name == child:
@@ -159,20 +170,23 @@
 
 	charts_map, paths = {}, []
 
-	line_no = 3
+	line_no = 2
 	error_messages = []
 
 	for i in data:
-		account_name, dummy, account_number, is_group, account_type, root_type = i
+		account_name, parent_account, account_number, parent_account_number, is_group, account_type, root_type = i
 
 		if not account_name:
 			error_messages.append("Row {0}: Please enter Account Name".format(line_no))
 
+		if account_number:
+			account_number = cstr(account_number).strip()
+			account_name = "{} - {}".format(account_number, account_name)
+
 		charts_map[account_name] = {}
 		if cint(is_group) == 1: charts_map[account_name]["is_group"] = is_group
 		if account_type: charts_map[account_name]["account_type"] = account_type
 		if root_type: charts_map[account_name]["root_type"] = root_type
-		if account_number: charts_map[account_name]["account_number"] = account_number
 		path = return_parent(data, account_name)[::-1]
 		paths.append(path) # List of path is created
 		line_no += 1
@@ -221,7 +235,7 @@
 
 def get_template(template_type):
 
-	fields = ["Account Name", "Parent Account", "Account Number", "Is Group", "Account Type", "Root Type"]
+	fields = ["Account Name", "Parent Account", "Account Number", "Parent Account Number", "Is Group", "Account Type", "Root Type"]
 	writer = UnicodeWriter()
 	writer.writerow(fields)
 
@@ -241,23 +255,23 @@
 
 def get_sample_template(writer):
 	template = [
-		["Application Of Funds(Assets)", "", "", 1, "", "Asset"],
-		["Sources Of Funds(Liabilities)", "", "", 1, "", "Liability"],
-		["Equity", "", "", 1, "", "Equity"],
-		["Expenses", "", "", 1, "", "Expense"],
-		["Income", "", "", 1, "", "Income"],
-		["Bank Accounts", "Application Of Funds(Assets)", "", 1, "Bank", "Asset"],
-		["Cash In Hand", "Application Of Funds(Assets)", "", 1, "Cash", "Asset"],
-		["Stock Assets", "Application Of Funds(Assets)", "", 1, "Stock", "Asset"],
-		["Cost Of Goods Sold", "Expenses", "", 0, "Cost of Goods Sold", "Expense"],
-		["Asset Depreciation", "Expenses", "", 0, "Depreciation", "Expense"],
-		["Fixed Assets", "Application Of Funds(Assets)", "", 0, "Fixed Asset", "Asset"],
-		["Accounts Payable", "Sources Of Funds(Liabilities)", "", 0, "Payable", "Liability"],
-		["Accounts Receivable", "Application Of Funds(Assets)", "", 1, "Receivable", "Asset"],
-		["Stock Expenses", "Expenses", "", 0, "Stock Adjustment", "Expense"],
-		["Sample Bank", "Bank Accounts", "", 0, "Bank", "Asset"],
-		["Cash", "Cash In Hand", "", 0, "Cash", "Asset"],
-		["Stores", "Stock Assets", "", 0, "Stock", "Asset"],
+		["Application Of Funds(Assets)", "", "", "", 1, "", "Asset"],
+		["Sources Of Funds(Liabilities)", "", "", "", 1, "", "Liability"],
+		["Equity", "", "", "", 1, "", "Equity"],
+		["Expenses", "", "", "", 1, "", "Expense"],
+		["Income", "", "", "", 1, "", "Income"],
+		["Bank Accounts", "Application Of Funds(Assets)", "", "", 1, "Bank", "Asset"],
+		["Cash In Hand", "Application Of Funds(Assets)", "", "", 1, "Cash", "Asset"],
+		["Stock Assets", "Application Of Funds(Assets)", "", "", 1, "Stock", "Asset"],
+		["Cost Of Goods Sold", "Expenses", "", "", 0, "Cost of Goods Sold", "Expense"],
+		["Asset Depreciation", "Expenses", "", "", 0, "Depreciation", "Expense"],
+		["Fixed Assets", "Application Of Funds(Assets)", "", "", 0, "Fixed Asset", "Asset"],
+		["Accounts Payable", "Sources Of Funds(Liabilities)", "", "", 0, "Payable", "Liability"],
+		["Accounts Receivable", "Application Of Funds(Assets)", "", "", 1, "Receivable", "Asset"],
+		["Stock Expenses", "Expenses", "", "", 0, "Stock Adjustment", "Expense"],
+		["Sample Bank", "Bank Accounts", "", "", 0, "Bank", "Asset"],
+		["Cash", "Cash In Hand", "", "", 0, "Cash", "Asset"],
+		["Stores", "Stock Assets", "", "", 0, "Stock", "Asset"],
 	]
 
 	for row in template:
diff --git a/erpnext/accounts/doctype/pricing_rule/pricing_rule.py b/erpnext/accounts/doctype/pricing_rule/pricing_rule.py
index 0565264..f0b4e29 100644
--- a/erpnext/accounts/doctype/pricing_rule/pricing_rule.py
+++ b/erpnext/accounts/doctype/pricing_rule/pricing_rule.py
@@ -136,7 +136,7 @@
 			for d in self.items:
 				max_discount = frappe.get_cached_value("Item", d.item_code, "max_discount")
 				if max_discount and flt(self.discount_percentage) > flt(max_discount):
-					throw(_("Max discount allowed for item: {0} is {1}%").format(self.item_code, max_discount))
+					throw(_("Max discount allowed for item: {0} is {1}%").format(d.item_code, max_discount))
 
 	def validate_price_list_with_currency(self):
 		if self.currency and self.for_price_list:
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
index d3e8a44..b361c0c 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
@@ -695,6 +695,7 @@
 				refresh_field(['timesheets'])
 			}
 		})
+		frm.refresh();
 	},
 
 	onload: function(frm) {
@@ -810,6 +811,65 @@
 	},
 
 	refresh: function(frm) {
+		if (frm.doc.project) {
+			frm.add_custom_button(__('Fetch Timesheet'), function() {
+				let d = new frappe.ui.Dialog({
+					title: __('Fetch Timesheet'),
+					fields: [
+						{
+							"label" : "From",
+							"fieldname": "from_time",
+							"fieldtype": "Date",
+							"reqd": 1,
+						},
+						{
+							fieldtype: 'Column Break',
+							fieldname: 'col_break_1',
+						},
+						{
+							"label" : "To",
+							"fieldname": "to_time",
+							"fieldtype": "Date",
+							"reqd": 1,
+						}
+					],
+					primary_action: function() {
+						let data = d.get_values();
+						frappe.call({
+							method: "erpnext.projects.doctype.timesheet.timesheet.get_projectwise_timesheet_data",
+							args: {
+								from_time: data.from_time,
+								to_time: data.to_time,
+								project: frm.doc.project
+							},
+							callback: function(r) {
+								if(!r.exc) {
+									if(r.message.length > 0) {
+										frm.clear_table('timesheets')
+										r.message.forEach((d) => {
+											frm.add_child('timesheets',{
+												'time_sheet': d.parent,
+												'billing_hours': d.billing_hours,
+												'billing_amount': d.billing_amt,
+												'timesheet_detail': d.name
+											});
+										});
+										frm.refresh_field('timesheets')
+									}
+									else {
+										frappe.msgprint(__('No Timesheet Found.'))
+									}
+									d.hide();
+								}
+							}
+						});
+					},
+					primary_action_label: __('Get Timesheets')
+				});
+				d.show();
+			})
+		}
+
 		if (frappe.boot.active_domains.includes("Healthcare")) {
 			frm.set_df_property("patient", "hidden", 0);
 			frm.set_df_property("patient_name", "hidden", 0);
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
index 4217711..4076be7 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
@@ -1059,7 +1059,8 @@
 			)
 
 	def make_gle_for_rounding_adjustment(self, gl_entries):
-		if flt(self.rounding_adjustment, self.precision("rounding_adjustment")) and self.base_rounding_adjustment:
+		if flt(self.rounding_adjustment, self.precision("rounding_adjustment")) and self.base_rounding_adjustment \
+			and not self.is_internal_transfer():
 			round_off_account, round_off_cost_center = \
 				get_round_off_account_and_cost_center(self.company)
 
diff --git a/erpnext/accounts/doctype/subscription/subscription.js b/erpnext/accounts/doctype/subscription/subscription.js
index ba98eb9..1a90664 100644
--- a/erpnext/accounts/doctype/subscription/subscription.js
+++ b/erpnext/accounts/doctype/subscription/subscription.js
@@ -10,6 +10,14 @@
 				}
 			}
 		});
+
+		frm.set_query('cost_center', function() {
+			return {
+				filters: {
+					company: frm.doc.company
+				}
+			};
+		});
 	},
 
 	refresh: function(frm) {
diff --git a/erpnext/accounts/doctype/subscription/subscription.json b/erpnext/accounts/doctype/subscription/subscription.json
index afb94fe..e80df2a 100644
--- a/erpnext/accounts/doctype/subscription/subscription.json
+++ b/erpnext/accounts/doctype/subscription/subscription.json
@@ -7,9 +7,10 @@
  "engine": "InnoDB",
  "field_order": [
   "party_type",
-  "status",
-  "cb_1",
   "party",
+  "cb_1",
+  "company",
+  "status",
   "subscription_period",
   "start_date",
   "end_date",
@@ -44,80 +45,107 @@
   {
    "allow_on_submit": 1,
    "fieldname": "cb_1",
-   "fieldtype": "Column Break"
+   "fieldtype": "Column Break",
+   "show_days": 1,
+   "show_seconds": 1
   },
   {
    "fieldname": "status",
    "fieldtype": "Select",
    "label": "Status",
+   "no_copy": 1,
    "options": "\nTrialling\nActive\nPast Due Date\nCancelled\nUnpaid\nCompleted",
-   "read_only": 1
+   "read_only": 1,
+   "show_days": 1,
+   "show_seconds": 1
   },
   {
    "fieldname": "subscription_period",
    "fieldtype": "Section Break",
-   "label": "Subscription Period"
+   "label": "Subscription Period",
+   "show_days": 1,
+   "show_seconds": 1
   },
   {
    "fieldname": "cancelation_date",
    "fieldtype": "Date",
    "label": "Cancelation Date",
-   "read_only": 1
+   "read_only": 1,
+   "show_days": 1,
+   "show_seconds": 1
   },
   {
    "allow_on_submit": 1,
    "fieldname": "trial_period_start",
    "fieldtype": "Date",
    "label": "Trial Period Start Date",
-   "set_only_once": 1
+   "set_only_once": 1,
+   "show_days": 1,
+   "show_seconds": 1
   },
   {
    "depends_on": "eval:doc.trial_period_start",
    "fieldname": "trial_period_end",
    "fieldtype": "Date",
    "label": "Trial Period End Date",
-   "set_only_once": 1
+   "set_only_once": 1,
+   "show_days": 1,
+   "show_seconds": 1
   },
   {
    "fieldname": "column_break_11",
-   "fieldtype": "Column Break"
+   "fieldtype": "Column Break",
+   "show_days": 1,
+   "show_seconds": 1
   },
   {
    "fieldname": "current_invoice_start",
    "fieldtype": "Date",
    "label": "Current Invoice Start Date",
-   "read_only": 1
+   "read_only": 1,
+   "show_days": 1,
+   "show_seconds": 1
   },
   {
    "fieldname": "current_invoice_end",
    "fieldtype": "Date",
    "label": "Current Invoice End Date",
-   "read_only": 1
+   "read_only": 1,
+   "show_days": 1,
+   "show_seconds": 1
   },
   {
    "default": "0",
    "description": "Number of days that the subscriber has to pay invoices generated by this subscription",
    "fieldname": "days_until_due",
    "fieldtype": "Int",
-   "label": "Days Until Due"
+   "label": "Days Until Due",
+   "show_days": 1,
+   "show_seconds": 1
   },
   {
    "default": "0",
    "fieldname": "cancel_at_period_end",
    "fieldtype": "Check",
-   "label": "Cancel At End Of Period"
+   "label": "Cancel At End Of Period",
+   "show_days": 1,
+   "show_seconds": 1
   },
   {
    "default": "0",
    "fieldname": "generate_invoice_at_period_start",
    "fieldtype": "Check",
-   "label": "Generate Invoice At Beginning Of Period"
+   "label": "Generate Invoice At Beginning Of Period",
+   "show_days": 1,
+   "show_seconds": 1
   },
   {
    "allow_on_submit": 1,
    "fieldname": "sb_4",
    "fieldtype": "Section Break",
-   "label": "Plans"
+   "label": "Plans",
+   "show_days": 1,
+   "show_seconds": 1
   },
   {
    "allow_on_submit": 1,
@@ -125,62 +153,84 @@
    "fieldtype": "Table",
    "label": "Plans",
    "options": "Subscription Plan Detail",
-   "reqd": 1
+   "reqd": 1,
+   "show_days": 1,
+   "show_seconds": 1
   },
   {
    "depends_on": "eval:['Customer', 'Supplier'].includes(doc.party_type)",
    "fieldname": "sb_1",
    "fieldtype": "Section Break",
-   "label": "Taxes"
+   "label": "Taxes",
+   "show_days": 1,
+   "show_seconds": 1
   },
   {
    "fieldname": "sb_2",
    "fieldtype": "Section Break",
-   "label": "Discounts"
+   "label": "Discounts",
+   "show_days": 1,
+   "show_seconds": 1
   },
   {
    "fieldname": "apply_additional_discount",
    "fieldtype": "Select",
    "label": "Apply Additional Discount On",
-   "options": "\nGrand Total\nNet Total"
+   "options": "\nGrand Total\nNet Total",
+   "show_days": 1,
+   "show_seconds": 1
   },
   {
    "fieldname": "cb_2",
-   "fieldtype": "Column Break"
+   "fieldtype": "Column Break",
+   "show_days": 1,
+   "show_seconds": 1
   },
   {
    "fieldname": "additional_discount_percentage",
    "fieldtype": "Percent",
-   "label": "Additional DIscount Percentage"
+   "label": "Additional DIscount Percentage",
+   "show_days": 1,
+   "show_seconds": 1
   },
   {
    "collapsible": 1,
    "fieldname": "additional_discount_amount",
    "fieldtype": "Currency",
-   "label": "Additional DIscount Amount"
+   "label": "Additional DIscount Amount",
+   "show_days": 1,
+   "show_seconds": 1
   },
   {
    "depends_on": "eval:doc.invoices",
    "fieldname": "sb_3",
    "fieldtype": "Section Break",
-   "label": "Invoices"
+   "label": "Invoices",
+   "show_days": 1,
+   "show_seconds": 1
   },
   {
    "collapsible": 1,
    "fieldname": "invoices",
    "fieldtype": "Table",
    "label": "Invoices",
-   "options": "Subscription Invoice"
+   "options": "Subscription Invoice",
+   "show_days": 1,
+   "show_seconds": 1
   },
   {
    "collapsible": 1,
    "fieldname": "accounting_dimensions_section",
    "fieldtype": "Section Break",
-   "label": "Accounting Dimensions"
+   "label": "Accounting Dimensions",
+   "show_days": 1,
+   "show_seconds": 1
   },
   {
    "fieldname": "dimension_col_break",
-   "fieldtype": "Column Break"
+   "fieldtype": "Column Break",
+   "show_days": 1,
+   "show_seconds": 1
   },
   {
    "fieldname": "party_type",
@@ -188,7 +238,9 @@
    "label": "Party Type",
    "options": "DocType",
    "reqd": 1,
-   "set_only_once": 1
+   "set_only_once": 1,
+   "show_days": 1,
+   "show_seconds": 1
   },
   {
    "fieldname": "party",
@@ -197,21 +249,27 @@
    "label": "Party",
    "options": "party_type",
    "reqd": 1,
-   "set_only_once": 1
+   "set_only_once": 1,
+   "show_days": 1,
+   "show_seconds": 1
   },
   {
    "depends_on": "eval:doc.party_type === 'Customer'",
    "fieldname": "sales_tax_template",
    "fieldtype": "Link",
    "label": "Sales Taxes and Charges Template",
-   "options": "Sales Taxes and Charges Template"
+   "options": "Sales Taxes and Charges Template",
+   "show_days": 1,
+   "show_seconds": 1
   },
   {
    "depends_on": "eval:doc.party_type === 'Supplier'",
    "fieldname": "purchase_tax_template",
    "fieldtype": "Link",
    "label": "Purchase Taxes and Charges Template",
-   "options": "Purchase Taxes and Charges Template"
+   "options": "Purchase Taxes and Charges Template",
+   "show_days": 1,
+   "show_seconds": 1
   },
   {
    "default": "0",
@@ -219,36 +277,55 @@
    "fieldname": "follow_calendar_months",
    "fieldtype": "Check",
    "label": "Follow Calendar Months",
-   "set_only_once": 1
+   "set_only_once": 1,
+   "show_days": 1,
+   "show_seconds": 1
   },
   {
    "default": "0",
    "description": "New invoices will be generated as per schedule even if current invoices are unpaid or past due date",
    "fieldname": "generate_new_invoices_past_due_date",
    "fieldtype": "Check",
-   "label": "Generate New Invoices Past Due Date"
+   "label": "Generate New Invoices Past Due Date",
+   "show_days": 1,
+   "show_seconds": 1
   },
   {
    "fieldname": "end_date",
    "fieldtype": "Date",
    "label": "Subscription End Date",
-   "set_only_once": 1
+   "set_only_once": 1,
+   "show_days": 1,
+   "show_seconds": 1
   },
   {
    "fieldname": "start_date",
    "fieldtype": "Date",
    "label": "Subscription Start Date",
-   "set_only_once": 1
+   "set_only_once": 1,
+   "show_days": 1,
+   "show_seconds": 1
   },
   {
    "fieldname": "cost_center",
    "fieldtype": "Link",
    "label": "Cost Center",
-   "options": "Cost Center"
+   "options": "Cost Center",
+   "show_days": 1,
+   "show_seconds": 1
+  },
+  {
+   "fieldname": "company",
+   "fieldtype": "Link",
+   "label": "Company",
+   "options": "Company",
+   "show_days": 1,
+   "show_seconds": 1
   }
  ],
+ "index_web_pages_for_search": 1,
  "links": [],
- "modified": "2020-06-25 10:52:52.265105",
+ "modified": "2021-02-09 15:44:20.024789",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "Subscription",
diff --git a/erpnext/accounts/doctype/subscription/subscription.py b/erpnext/accounts/doctype/subscription/subscription.py
index e023b47..826044a 100644
--- a/erpnext/accounts/doctype/subscription/subscription.py
+++ b/erpnext/accounts/doctype/subscription/subscription.py
@@ -1,3 +1,4 @@
+
 # -*- coding: utf-8 -*-
 # Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
 # For license information, please see license.txt
@@ -5,12 +6,13 @@
 from __future__ import unicode_literals
 
 import frappe
+import erpnext
 from frappe import _
 from frappe.model.document import Document
 from frappe.utils.data import nowdate, getdate, cstr, cint, add_days, date_diff, get_last_day, add_to_date, flt
 from erpnext.accounts.doctype.subscription_plan.subscription_plan import get_plan_rate
 from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_accounting_dimensions
-
+from erpnext import get_default_company
 
 class Subscription(Document):
 	def before_insert(self):
@@ -243,6 +245,7 @@
 		self.validate_plans_billing_cycle(self.get_billing_cycle_and_interval())
 		self.validate_end_date()
 		self.validate_to_follow_calendar_months()
+		self.cost_center = erpnext.get_default_cost_center(self.get('company'))
 
 	def validate_trial_period(self):
 		"""
@@ -304,6 +307,14 @@
 		doctype = 'Sales Invoice' if self.party_type == 'Customer' else 'Purchase Invoice'
 
 		invoice = frappe.new_doc(doctype)
+
+		# For backward compatibility
+		# Earlier subscription didn't had any company field
+		company = self.get('company') or get_default_company()
+		if not company:
+			frappe.throw(_("Company is mandatory was generating invoice. Please set default company in Global Defaults"))
+
+		invoice.company = company
 		invoice.set_posting_time = 1
 		invoice.posting_date = self.current_invoice_start if self.generate_invoice_at_period_start \
 			else self.current_invoice_end
@@ -330,6 +341,7 @@
 		# for that reason
 		items_list = self.get_items_from_plans(self.plans, prorate)
 		for item in items_list:
+			item['cost_center'] = self.cost_center
 			invoice.append('items', item)
 
 		# Taxes
@@ -380,7 +392,8 @@
 		Returns the `Item`s linked to `Subscription Plan`
 		"""
 		if prorate:
-			prorate_factor = get_prorata_factor(self.current_invoice_end, self.current_invoice_start)
+			prorate_factor = get_prorata_factor(self.current_invoice_end, self.current_invoice_start,
+				self.generate_invoice_at_period_start)
 
 		items = []
 		party = self.party
@@ -583,10 +596,13 @@
 
 	return calendar_months
 
-def get_prorata_factor(period_end, period_start):
-	diff = flt(date_diff(nowdate(), period_start) + 1)
-	plan_days = flt(date_diff(period_end, period_start) + 1)
-	prorate_factor = diff / plan_days
+def get_prorata_factor(period_end, period_start, is_prepaid):
+	if is_prepaid:
+		prorate_factor = 1
+	else:
+		diff = flt(date_diff(nowdate(), period_start) + 1)
+		plan_days = flt(date_diff(period_end, period_start) + 1)
+		prorate_factor = diff / plan_days
 
 	return prorate_factor
 
diff --git a/erpnext/accounts/doctype/subscription/test_subscription.py b/erpnext/accounts/doctype/subscription/test_subscription.py
index c17fccd..7c58e98 100644
--- a/erpnext/accounts/doctype/subscription/test_subscription.py
+++ b/erpnext/accounts/doctype/subscription/test_subscription.py
@@ -321,7 +321,8 @@
 
 		self.assertEqual(
 			flt(
-				get_prorata_factor(subscription.current_invoice_end, subscription.current_invoice_start),
+				get_prorata_factor(subscription.current_invoice_end, subscription.current_invoice_start,
+					subscription.generate_invoice_at_period_start),
 				2),
 			flt(prorate_factor, 2)
 		)
@@ -561,9 +562,7 @@
 		current_inv = subscription.get_current_invoice()
 		self.assertEqual(current_inv.status, "Unpaid")
 
-		diff = flt(date_diff(nowdate(), subscription.current_invoice_start) + 1)
-		plan_days = flt(date_diff(subscription.current_invoice_end, subscription.current_invoice_start) + 1)
-		prorate_factor = flt(diff / plan_days)
+		prorate_factor = 1
 
 		self.assertEqual(flt(current_inv.grand_total, 2), flt(prorate_factor * 900, 2))
 
diff --git a/erpnext/accounts/doctype/subscription_invoice/subscription_invoice.json b/erpnext/accounts/doctype/subscription_invoice/subscription_invoice.json
index f54e887..8a0d1de 100644
--- a/erpnext/accounts/doctype/subscription_invoice/subscription_invoice.json
+++ b/erpnext/accounts/doctype/subscription_invoice/subscription_invoice.json
@@ -13,21 +13,28 @@
    "fieldname": "document_type",
    "fieldtype": "Link",
    "label": "Document Type ",
+   "no_copy": 1,
    "options": "DocType",
-   "read_only": 1
+   "read_only": 1,
+   "show_days": 1,
+   "show_seconds": 1
   },
   {
    "fieldname": "invoice",
    "fieldtype": "Dynamic Link",
    "in_list_view": 1,
    "label": "Invoice",
+   "no_copy": 1,
    "options": "document_type",
-   "read_only": 1
+   "read_only": 1,
+   "show_days": 1,
+   "show_seconds": 1
   }
  ],
+ "index_web_pages_for_search": 1,
  "istable": 1,
  "links": [],
- "modified": "2020-06-01 22:23:54.462718",
+ "modified": "2021-02-09 15:43:32.026233",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "Subscription Invoice",
diff --git a/erpnext/accounts/general_ledger.py b/erpnext/accounts/general_ledger.py
index b42c0c6..dac0c21 100644
--- a/erpnext/accounts/general_ledger.py
+++ b/erpnext/accounts/general_ledger.py
@@ -196,7 +196,7 @@
 
 	if not round_off_gle:
 		for k in ["voucher_type", "voucher_no", "company",
-			"posting_date", "remarks", "is_opening"]:
+			"posting_date", "remarks"]:
 				round_off_gle[k] = gl_map[0][k]
 
 	round_off_gle.update({
@@ -208,6 +208,7 @@
 		"cost_center": round_off_cost_center,
 		"party_type": None,
 		"party": None,
+		"is_opening": "No",
 		"against_voucher_type": None,
 		"against_voucher": None
 	})
diff --git a/erpnext/accounts/party.py b/erpnext/accounts/party.py
index 38b2284..e01cb6e 100644
--- a/erpnext/accounts/party.py
+++ b/erpnext/accounts/party.py
@@ -617,6 +617,7 @@
 		FROM `tabGL Entry`
 		WHERE
 			party_type = %s and against_voucher is null
+			and is_cancelled = 0
 			and {1} GROUP BY party"""
 		.format(("credit") if party_type == "Customer" else "debit", cond) , party_type)
 
diff --git a/erpnext/controllers/selling_controller.py b/erpnext/controllers/selling_controller.py
index c61b67b..fb52c1f 100644
--- a/erpnext/controllers/selling_controller.py
+++ b/erpnext/controllers/selling_controller.py
@@ -142,6 +142,11 @@
 				self.base_net_total * sales_person.allocated_percentage / 100.0,
 				self.precision("allocated_amount", sales_person))
 
+			if sales_person.commission_rate:
+				sales_person.incentives = flt(
+					sales_person.allocated_amount * flt(sales_person.commission_rate) / 100.0, 
+					self.precision("incentives", sales_person))
+
 			total += sales_person.allocated_percentage
 
 		if sales_team and total != 100.0:
diff --git a/erpnext/erpnext_integrations/doctype/amazon_mws_settings/amazon_methods.py b/erpnext/erpnext_integrations/doctype/amazon_mws_settings/amazon_methods.py
index cc75a0a..148c1a6 100644
--- a/erpnext/erpnext_integrations/doctype/amazon_mws_settings/amazon_methods.py
+++ b/erpnext/erpnext_integrations/doctype/amazon_mws_settings/amazon_methods.py
@@ -117,7 +117,7 @@
 			return response
 		except Exception as e:
 			delay = math.pow(4, x) * 125
-			frappe.log_error(message=e, title=str(mws_method))
+			frappe.log_error(message=e, title=f'Method "{mws_method.__name__}" failed')
 			time.sleep(delay)
 			continue
 
diff --git a/erpnext/hooks.py b/erpnext/hooks.py
index 39d3659..59639ff 100644
--- a/erpnext/hooks.py
+++ b/erpnext/hooks.py
@@ -393,6 +393,15 @@
 
 communication_doctypes = ["Customer", "Supplier"]
 
+accounting_dimension_doctypes = ["GL Entry", "Sales Invoice", "Purchase Invoice", "Payment Entry", "Asset",
+	"Expense Claim", "Expense Claim Detail", "Expense Taxes and Charges", "Stock Entry", "Budget", "Payroll Entry", "Delivery Note",
+	"Sales Invoice Item", "Purchase Invoice Item", "Purchase Order Item", "Journal Entry Account", "Material Request Item", "Delivery Note Item",
+	"Purchase Receipt Item", "Stock Entry Detail", "Payment Entry Deduction", "Sales Taxes and Charges", "Purchase Taxes and Charges", "Shipping Rule",
+	"Landed Cost Item", "Asset Value Adjustment", "Loyalty Program", "Fee Schedule", "Fee Structure", "Stock Reconciliation",
+	"Travel Request", "Fees", "POS Profile", "Opening Invoice Creation Tool", "Opening Invoice Creation Tool Item", "Subscription",
+	"Subscription Plan"
+]
+
 regional_overrides = {
 	'France': {
 		'erpnext.tests.test_regional.test_method': 'erpnext.regional.france.utils.test_method'
diff --git a/erpnext/hr/doctype/hr_settings/hr_settings.json b/erpnext/hr/doctype/hr_settings/hr_settings.json
index f999635..d8aae66 100644
--- a/erpnext/hr/doctype/hr_settings/hr_settings.json
+++ b/erpnext/hr/doctype/hr_settings/hr_settings.json
@@ -138,7 +138,7 @@
  "idx": 1,
  "issingle": 1,
  "links": [],
- "modified": "2020-08-27 14:30:28.995324",
+ "modified": "2021-02-25 12:31:14.947865",
  "modified_by": "Administrator",
  "module": "HR",
  "name": "HR Settings",
@@ -155,5 +155,6 @@
   }
  ],
  "sort_field": "modified",
- "sort_order": "ASC"
-}
+ "sort_order": "ASC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/hr/doctype/leave_allocation/leave_allocation.py b/erpnext/hr/doctype/leave_allocation/leave_allocation.py
index 5e3822e..69d605d 100755
--- a/erpnext/hr/doctype/leave_allocation/leave_allocation.py
+++ b/erpnext/hr/doctype/leave_allocation/leave_allocation.py
@@ -18,7 +18,6 @@
 class LeaveAllocation(Document):
 	def validate(self):
 		self.validate_period()
-		self.validate_new_leaves_allocated_value()
 		self.validate_allocation_overlap()
 		self.validate_back_dated_allocation()
 		self.set_total_leaves_allocated()
@@ -72,11 +71,6 @@
 		if frappe.db.get_value("Leave Type", self.leave_type, "is_lwp"):
 			frappe.throw(_("Leave Type {0} cannot be allocated since it is leave without pay").format(self.leave_type))
 
-	def validate_new_leaves_allocated_value(self):
-		"""validate that leave allocation is in multiples of 0.5"""
-		if flt(self.new_leaves_allocated) % 0.5:
-			frappe.throw(_("Leaves must be allocated in multiples of 0.5"), ValueMultiplierError)
-
 	def validate_allocation_overlap(self):
 		leave_allocation = frappe.db.sql("""
 			SELECT
diff --git a/erpnext/hr/doctype/leave_policy_assignment/leave_policy_assignment.json b/erpnext/hr/doctype/leave_policy_assignment/leave_policy_assignment.json
index a0327bd..3373350 100644
--- a/erpnext/hr/doctype/leave_policy_assignment/leave_policy_assignment.json
+++ b/erpnext/hr/doctype/leave_policy_assignment/leave_policy_assignment.json
@@ -106,12 +106,14 @@
    "fieldname": "leaves_allocated",
    "fieldtype": "Check",
    "hidden": 1,
-   "label": "Leaves Allocated"
+   "label": "Leaves Allocated",
+   "no_copy": 1,
+   "print_hide": 1
   }
  ],
  "is_submittable": 1,
  "links": [],
- "modified": "2020-12-31 16:43:30.695206",
+ "modified": "2021-03-01 17:54:01.014509",
  "modified_by": "Administrator",
  "module": "HR",
  "name": "Leave Policy Assignment",
diff --git a/erpnext/hr/doctype/leave_policy_assignment/leave_policy_assignment.py b/erpnext/hr/doctype/leave_policy_assignment/leave_policy_assignment.py
index a5068bc..4064c56 100644
--- a/erpnext/hr/doctype/leave_policy_assignment/leave_policy_assignment.py
+++ b/erpnext/hr/doctype/leave_policy_assignment/leave_policy_assignment.py
@@ -6,7 +6,7 @@
 import frappe
 from frappe.model.document import Document
 from frappe import _, bold
-from frappe.utils import getdate, date_diff, comma_and, formatdate
+from frappe.utils import getdate, date_diff, comma_and, formatdate, get_datetime, flt
 from math import ceil
 import json
 from six import string_types
@@ -84,17 +84,52 @@
 		return allocation.name, new_leaves_allocated
 
 	def get_new_leaves(self, leave_type, new_leaves_allocated, leave_type_details, date_of_joining):
+		from frappe.model.meta import get_field_precision
+		precision = get_field_precision(frappe.get_meta("Leave Allocation").get_field("new_leaves_allocated"))
+
+		# Earned Leaves and Compensatory Leaves are allocated by scheduler, initially allocate 0
+		if leave_type_details.get(leave_type).is_compensatory == 1:
+			new_leaves_allocated = 0
+
+		elif leave_type_details.get(leave_type).is_earned_leave == 1:
+			if self.assignment_based_on == "Leave Period":
+				new_leaves_allocated = self.get_leaves_for_passed_months(leave_type, new_leaves_allocated, leave_type_details, date_of_joining)
+			else:
+				new_leaves_allocated = 0
 		# 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):
+		elif 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 flt(new_leaves_allocated, precision)
+
+	def get_leaves_for_passed_months(self, leave_type, new_leaves_allocated, leave_type_details, date_of_joining):
+		from erpnext.hr.utils import get_monthly_earned_leave
+
+		current_month = get_datetime().month
+		current_year = get_datetime().year
+
+		from_date = frappe.db.get_value("Leave Period", self.leave_period, "from_date")
+		if getdate(date_of_joining) > getdate(from_date):
+			from_date = date_of_joining
+
+		from_date_month = get_datetime(from_date).month
+		from_date_year = get_datetime(from_date).year
+
+		months_passed = 0
+		if current_year == from_date_year and current_month > from_date_month:
+			months_passed = current_month - from_date_month
+		elif current_year > from_date_year:
+			months_passed = (12 - from_date_month) + current_month
+
+		if months_passed > 0:
+			monthly_earned_leave = get_monthly_earned_leave(new_leaves_allocated,
+				leave_type_details.get(leave_type).earned_leave_frequency, leave_type_details.get(leave_type).rounding)
+			new_leaves_allocated = monthly_earned_leave * months_passed
 
 		return new_leaves_allocated
 
+
 @frappe.whitelist()
 def grant_leave_for_multiple_employees(leave_policy_assignments):
 	leave_policy_assignments = json.loads(leave_policy_assignments)
@@ -156,7 +191,8 @@
 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"])
+		fields=["name", "is_lwp", "is_earned_leave", "is_compensatory",
+			"is_carry_forward", "expire_carry_forwarded_leaves_after_days", "earned_leave_frequency", "rounding"])
 	for d in leave_types:
 		leave_type_details.setdefault(d.name, d)
 	return leave_type_details
diff --git a/erpnext/hr/doctype/leave_type/leave_type.json b/erpnext/hr/doctype/leave_type/leave_type.json
index a209291..fc577ef 100644
--- a/erpnext/hr/doctype/leave_type/leave_type.json
+++ b/erpnext/hr/doctype/leave_type/leave_type.json
@@ -172,7 +172,7 @@
    "fieldname": "rounding",
    "fieldtype": "Select",
    "label": "Rounding",
-   "options": "0.5\n1.0"
+   "options": "\n0.25\n0.5\n1.0"
   },
   {
    "depends_on": "is_carry_forward",
@@ -197,6 +197,7 @@
    "label": "Based On Date Of Joining"
   },
   {
+   "default": "0",
    "depends_on": "eval:doc.is_lwp == 0",
    "fieldname": "is_ppl",
    "fieldtype": "Check",
@@ -213,7 +214,7 @@
  "icon": "fa fa-flag",
  "idx": 1,
  "links": [],
- "modified": "2020-10-15 15:49:47.555105",
+ "modified": "2021-03-02 11:22:33.776320",
  "modified_by": "Administrator",
  "module": "HR",
  "name": "Leave Type",
diff --git a/erpnext/hr/doctype/skill/skill.json b/erpnext/hr/doctype/skill/skill.json
index 5182973..4c8a8c9 100644
--- a/erpnext/hr/doctype/skill/skill.json
+++ b/erpnext/hr/doctype/skill/skill.json
@@ -3,7 +3,7 @@
  "allow_events_in_timeline": 0,
  "allow_guest_to_view": 0,
  "allow_import": 0,
- "allow_rename": 0,
+ "allow_rename": 1,
  "autoname": "field:skill_name",
  "beta": 0,
  "creation": "2019-04-16 09:54:39.486915",
@@ -16,7 +16,7 @@
  "fields": [
   {
    "allow_bulk_edit": 0,
-   "allow_in_quick_entry": 0,
+   "allow_in_quick_entry": 1,
    "allow_on_submit": 0,
    "bold": 0,
    "collapsible": 0,
@@ -46,6 +46,12 @@
    "set_only_once": 0,
    "translatable": 0,
    "unique": 1
+  },
+  {
+   "allow_in_quick_entry": 1,
+   "fieldname": "description",
+   "fieldtype": "Text",
+   "label": "Description"
   }
  ],
  "has_web_view": 0,
@@ -56,7 +62,7 @@
  "issingle": 0,
  "istable": 0,
  "max_attachments": 0,
- "modified": "2019-04-16 09:55:00.536328",
+ "modified": "2021-02-26 10:55:00.536328",
  "modified_by": "Administrator",
  "module": "HR",
  "name": "Skill",
@@ -110,4 +116,4 @@
  "track_changes": 1,
  "track_seen": 0,
  "track_views": 0
-}
\ No newline at end of file
+}
diff --git a/erpnext/hr/utils.py b/erpnext/hr/utils.py
index e2aa7a4..d57ef59 100644
--- a/erpnext/hr/utils.py
+++ b/erpnext/hr/utils.py
@@ -316,13 +316,7 @@
 				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)
+		earned_leaves = get_monthly_earned_leave(annual_allocation, e_leave_type.earned_leave_frequency, e_leave_type.rounding)
 
 		allocation = frappe.get_doc('Leave Allocation', allocation.name)
 		new_allocation = flt(allocation.total_leaves_allocated) + flt(earned_leaves)
@@ -335,6 +329,21 @@
 			today_date = today()
 			create_additional_leave_ledger_entry(allocation, earned_leaves, today_date)
 
+def get_monthly_earned_leave(annual_leaves, frequency, rounding):
+	earned_leaves = 0.0
+	divide_by_frequency = {"Yearly": 1, "Half-Yearly": 6, "Quarterly": 4, "Monthly": 12}
+	if annual_leaves:
+		earned_leaves = flt(annual_leaves) / divide_by_frequency[frequency]
+		if rounding:
+			if rounding == "0.25":
+				earned_leaves = round(earned_leaves * 4) / 4
+			elif rounding == "0.5":
+				earned_leaves = round(earned_leaves * 2) / 2
+			else:
+				earned_leaves = round(earned_leaves)
+
+	return earned_leaves
+
 
 def get_leave_allocations(date, leave_type):
 	return frappe.db.sql("""select name, employee, from_date, to_date, leave_policy_assignment, leave_policy
diff --git a/erpnext/patches/v13_0/item_reposting_for_incorrect_sl_and_gl.py b/erpnext/patches/v13_0/item_reposting_for_incorrect_sl_and_gl.py
index ca04e8a..d968e1f 100644
--- a/erpnext/patches/v13_0/item_reposting_for_incorrect_sl_and_gl.py
+++ b/erpnext/patches/v13_0/item_reposting_for_incorrect_sl_and_gl.py
@@ -1,13 +1,24 @@
 import frappe
 from frappe import _
-from frappe.utils import getdate, get_time
+from frappe.utils import getdate, get_time, today
 from erpnext.stock.stock_ledger import update_entries_after
 from erpnext.accounts.utils import update_gl_entries_after
 
 def execute():
-	frappe.reload_doc('stock', 'doctype', 'repost_item_valuation')
+	for doctype in ('repost_item_valuation', 'stock_entry_detail', 'purchase_receipt_item',
+			'purchase_invoice_item', 'delivery_note_item', 'sales_invoice_item', 'packed_item'):
+		frappe.reload_doc('stock', 'doctype', doctype)
+	frappe.reload_doc('buying', 'doctype', 'purchase_receipt_item_supplied')
 
-	reposting_project_deployed_on = frappe.db.get_value("DocType", "Repost Item Valuation", "creation")
+	reposting_project_deployed_on = get_creation_time()
+	posting_date = getdate(reposting_project_deployed_on)
+	posting_time = get_time(reposting_project_deployed_on)
+
+	if posting_date == today():
+		return
+
+	frappe.clear_cache()
+	frappe.flags.warehouse_account_map = {}
 
 	data = frappe.db.sql('''
 		SELECT
@@ -41,10 +52,12 @@
 
 
 	print("Reposting General Ledger Entries...")
-	posting_date = getdate(reposting_project_deployed_on)
-	posting_time = get_time(reposting_project_deployed_on)
 
 	for row in frappe.get_all('Company', filters= {'enable_perpetual_inventory': 1}):
 		update_gl_entries_after(posting_date, posting_time, company=row.name)
 
 	frappe.db.auto_commit_on_many_writes = 0
+
+def get_creation_time():
+	return frappe.db.sql(''' SELECT create_time FROM
+		INFORMATION_SCHEMA.TABLES where TABLE_NAME = "tabRepost Item Valuation" ''', as_list=1)[0][0]
\ No newline at end of file
diff --git a/erpnext/payroll/doctype/payroll_settings/payroll_settings.json b/erpnext/payroll/doctype/payroll_settings/payroll_settings.json
index c47caa1..680e518 100644
--- a/erpnext/payroll/doctype/payroll_settings/payroll_settings.json
+++ b/erpnext/payroll/doctype/payroll_settings/payroll_settings.json
@@ -15,6 +15,7 @@
   "daily_wages_fraction_for_half_day",
   "email_salary_slip_to_employee",
   "encrypt_salary_slips_in_emails",
+  "show_leave_balances_in_salary_slip",
   "password_policy"
  ],
  "fields": [
@@ -23,58 +24,44 @@
    "fieldname": "payroll_based_on",
    "fieldtype": "Select",
    "label": "Calculate Payroll Working Days Based On",
-   "options": "Leave\nAttendance",
-   "show_days": 1,
-   "show_seconds": 1
+   "options": "Leave\nAttendance"
   },
   {
    "fieldname": "max_working_hours_against_timesheet",
    "fieldtype": "Float",
-   "label": "Max working hours against Timesheet",
-   "show_days": 1,
-   "show_seconds": 1
+   "label": "Max working hours against Timesheet"
   },
   {
    "default": "0",
    "description": "If checked, Total no. of Working Days will include holidays, and this will reduce the value of Salary Per Day",
    "fieldname": "include_holidays_in_total_working_days",
    "fieldtype": "Check",
-   "label": "Include holidays in Total no. of Working Days",
-   "show_days": 1,
-   "show_seconds": 1
+   "label": "Include holidays in Total no. of Working Days"
   },
   {
    "default": "0",
    "description": "If checked, hides and disables Rounded Total field in Salary Slips",
    "fieldname": "disable_rounded_total",
    "fieldtype": "Check",
-   "label": "Disable Rounded Total",
-   "show_days": 1,
-   "show_seconds": 1
+   "label": "Disable Rounded Total"
   },
   {
    "fieldname": "column_break_11",
-   "fieldtype": "Column Break",
-   "show_days": 1,
-   "show_seconds": 1
+   "fieldtype": "Column Break"
   },
   {
    "default": "0.5",
    "description": "The fraction of daily wages to be paid for half-day attendance",
    "fieldname": "daily_wages_fraction_for_half_day",
    "fieldtype": "Float",
-   "label": "Fraction of Daily Salary for Half Day",
-   "show_days": 1,
-   "show_seconds": 1
+   "label": "Fraction of Daily Salary for Half Day"
   },
   {
    "default": "1",
    "description": "Emails salary slip to employee based on preferred email selected in Employee",
    "fieldname": "email_salary_slip_to_employee",
    "fieldtype": "Check",
-   "label": "Email Salary Slip to Employee",
-   "show_days": 1,
-   "show_seconds": 1
+   "label": "Email Salary Slip to Employee"
   },
   {
    "default": "0",
@@ -82,9 +69,7 @@
    "description": "The salary slip emailed to the employee will be password protected, the password will be generated based on the password policy.",
    "fieldname": "encrypt_salary_slips_in_emails",
    "fieldtype": "Check",
-   "label": "Encrypt Salary Slips in Emails",
-   "show_days": 1,
-   "show_seconds": 1
+   "label": "Encrypt Salary Slips in Emails"
   },
   {
    "depends_on": "eval: doc.encrypt_salary_slips_in_emails == 1",
@@ -92,24 +77,27 @@
    "fieldname": "password_policy",
    "fieldtype": "Data",
    "in_list_view": 1,
-   "label": "Password Policy",
-   "show_days": 1,
-   "show_seconds": 1
+   "label": "Password Policy"
   },
   {
    "depends_on": "eval:doc.payroll_based_on == 'Attendance'",
    "fieldname": "consider_unmarked_attendance_as",
    "fieldtype": "Select",
    "label": "Consider Unmarked Attendance As",
-   "options": "Present\nAbsent",
-   "show_days": 1,
-   "show_seconds": 1
+   "options": "Present\nAbsent"
+  },
+  {
+   "default": "0",
+   "fieldname": "show_leave_balances_in_salary_slip",
+   "fieldtype": "Check",
+   "label": "Show Leave Balances in Salary Slip"
   }
  ],
  "icon": "fa fa-cog",
+ "index_web_pages_for_search": 1,
  "issingle": 1,
  "links": [],
- "modified": "2020-06-22 17:00:58.408030",
+ "modified": "2021-02-19 11:07:55.873991",
  "modified_by": "Administrator",
  "module": "Payroll",
  "name": "Payroll Settings",
diff --git a/erpnext/payroll/doctype/salary_slip/salary_slip.json b/erpnext/payroll/doctype/salary_slip/salary_slip.json
index 9f9691b..6688368 100644
--- a/erpnext/payroll/doctype/salary_slip/salary_slip.json
+++ b/erpnext/payroll/doctype/salary_slip/salary_slip.json
@@ -80,6 +80,8 @@
   "total_in_words",
   "column_break_69",
   "base_total_in_words",
+  "leave_details_section",
+  "leave_details",
   "section_break_75",
   "amended_from"
  ],
@@ -612,13 +614,25 @@
    "label": "Month To Date(Company Currency)",
    "options": "Company:company:default_currency",
    "read_only": 1
+  },
+  {
+   "fieldname": "leave_details_section",
+   "fieldtype": "Section Break",
+   "label": "Leave Details"
+  },
+  {
+   "fieldname": "leave_details",
+   "fieldtype": "Table",
+   "label": "Leave Details",
+   "options": "Salary Slip Leave",
+   "read_only": 1
   }
  ],
  "icon": "fa fa-file-text",
  "idx": 9,
  "is_submittable": 1,
  "links": [],
- "modified": "2021-01-14 13:37:38.180920",
+ "modified": "2021-02-19 11:48:05.383945",
  "modified_by": "Administrator",
  "module": "Payroll",
  "name": "Salary Slip",
diff --git a/erpnext/payroll/doctype/salary_slip/salary_slip.py b/erpnext/payroll/doctype/salary_slip/salary_slip.py
index 60aff02..d9aadbf 100644
--- a/erpnext/payroll/doctype/salary_slip/salary_slip.py
+++ b/erpnext/payroll/doctype/salary_slip/salary_slip.py
@@ -19,6 +19,7 @@
 from erpnext.payroll.doctype.employee_benefit_claim.employee_benefit_claim import get_benefit_claim_amount, get_last_payroll_period_benefits
 from erpnext.loan_management.doctype.loan_repayment.loan_repayment import calculate_amounts, create_repayment_entry
 from erpnext.accounts.utils import get_fiscal_year
+from six import iteritems
 
 class SalarySlip(TransactionBase):
 	def __init__(self, *args, **kwargs):
@@ -53,6 +54,7 @@
 		self.compute_year_to_date()
 		self.compute_month_to_date()
 		self.compute_component_wise_year_to_date()
+		self.add_leave_balances()
 
 		if frappe.db.get_single_value("Payroll Settings", "max_working_hours_against_timesheet"):
 			max_working_hours = frappe.db.get_single_value("Payroll Settings", "max_working_hours_against_timesheet")
@@ -1123,6 +1125,7 @@
 	#calculate total working hours, earnings based on hourly wages and totals
 	def calculate_total_for_salary_slip_based_on_timesheet(self):
 		if self.timesheets:
+			self.total_working_hours = 0
 			for timesheet in self.timesheets:
 				if timesheet.working_hours:
 					self.total_working_hours += timesheet.working_hours
@@ -1212,6 +1215,22 @@
 
 		return period_start_date, period_end_date
 
+	def add_leave_balances(self):
+		self.set('leave_details', [])
+
+		if frappe.db.get_single_value('Payroll Settings', 'show_leave_balances_in_salary_slip'):
+			from erpnext.hr.doctype.leave_application.leave_application import get_leave_details
+			leave_details = get_leave_details(self.employee, self.end_date)
+
+			for leave_type, leave_values in iteritems(leave_details['leave_allocation']):
+				self.append('leave_details', {
+					'leave_type': leave_type,
+					'total_allocated_leaves': flt(leave_values.get('total_leaves')),
+					'expired_leaves': flt(leave_values.get('expired_leaves')),
+					'used_leaves': flt(leave_values.get('leaves_taken')),
+					'pending_leaves': flt(leave_values.get('pending_leaves')),
+					'available_leaves': flt(leave_values.get('remaining_leaves'))
+				})
 
 def unlink_ref_doc_from_salary_slip(ref_no):
 	linked_ss = frappe.db.sql_list("""select name from `tabSalary Slip`
diff --git a/erpnext/payroll/doctype/salary_slip_leave/__init__.py b/erpnext/payroll/doctype/salary_slip_leave/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/payroll/doctype/salary_slip_leave/__init__.py
diff --git a/erpnext/payroll/doctype/salary_slip_leave/salary_slip_leave.json b/erpnext/payroll/doctype/salary_slip_leave/salary_slip_leave.json
new file mode 100644
index 0000000..7ac453b
--- /dev/null
+++ b/erpnext/payroll/doctype/salary_slip_leave/salary_slip_leave.json
@@ -0,0 +1,78 @@
+{
+ "actions": [],
+ "creation": "2021-02-19 11:45:18.173417",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "leave_type",
+  "total_allocated_leaves",
+  "expired_leaves",
+  "used_leaves",
+  "pending_leaves",
+  "available_leaves"
+ ],
+ "fields": [
+  {
+   "fieldname": "leave_type",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "label": "Leave Type",
+   "no_copy": 1,
+   "options": "Leave Type",
+   "read_only": 1
+  },
+  {
+   "fieldname": "total_allocated_leaves",
+   "fieldtype": "Float",
+   "in_list_view": 1,
+   "label": "Total Allocated Leave",
+   "no_copy": 1,
+   "read_only": 1
+  },
+  {
+   "fieldname": "expired_leaves",
+   "fieldtype": "Float",
+   "in_list_view": 1,
+   "label": "Expired Leave",
+   "no_copy": 1,
+   "read_only": 1
+  },
+  {
+   "fieldname": "used_leaves",
+   "fieldtype": "Float",
+   "in_list_view": 1,
+   "label": "Used Leave",
+   "no_copy": 1,
+   "read_only": 1
+  },
+  {
+   "fieldname": "pending_leaves",
+   "fieldtype": "Float",
+   "in_list_view": 1,
+   "label": "Pending Leave",
+   "no_copy": 1,
+   "read_only": 1
+  },
+  {
+   "fieldname": "available_leaves",
+   "fieldtype": "Float",
+   "in_list_view": 1,
+   "label": "Available Leave",
+   "no_copy": 1,
+   "read_only": 1
+  }
+ ],
+ "index_web_pages_for_search": 1,
+ "istable": 1,
+ "links": [],
+ "modified": "2021-02-19 10:47:48.546724",
+ "modified_by": "Administrator",
+ "module": "Payroll",
+ "name": "Salary Slip Leave",
+ "owner": "Administrator",
+ "permissions": [],
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/payroll/doctype/salary_slip_leave/salary_slip_leave.py b/erpnext/payroll/doctype/salary_slip_leave/salary_slip_leave.py
new file mode 100644
index 0000000..7a92bf1
--- /dev/null
+++ b/erpnext/payroll/doctype/salary_slip_leave/salary_slip_leave.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2021, 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 SalarySlipLeave(Document):
+	pass
diff --git a/erpnext/projects/doctype/project_template_task/project_template_task.json b/erpnext/projects/doctype/project_template_task/project_template_task.json
index 69530b1..16caaa2 100644
--- a/erpnext/projects/doctype/project_template_task/project_template_task.json
+++ b/erpnext/projects/doctype/project_template_task/project_template_task.json
@@ -20,6 +20,7 @@
   },
   {
    "columns": 6,
+   "fetch_from": "task.subject",
    "fieldname": "subject",
    "fieldtype": "Read Only",
    "in_list_view": 1,
@@ -28,7 +29,7 @@
  ],
  "istable": 1,
  "links": [],
- "modified": "2021-01-07 15:13:40.995071",
+ "modified": "2021-02-24 15:18:49.095071",
  "modified_by": "Administrator",
  "module": "Projects",
  "name": "Project Template Task",
diff --git a/erpnext/projects/doctype/task/task.py b/erpnext/projects/doctype/task/task.py
index 7116348..855ff5f 100755
--- a/erpnext/projects/doctype/task/task.py
+++ b/erpnext/projects/doctype/task/task.py
@@ -17,319 +17,326 @@
 class EndDateCannotBeGreaterThanProjectEndDateError(frappe.ValidationError): pass
 
 class Task(NestedSet):
-    nsm_parent_field = 'parent_task'
+	nsm_parent_field = 'parent_task'
 
-    def get_feed(self):
-        return '{0}: {1}'.format(_(self.status), self.subject)
+	def get_feed(self):
+		return '{0}: {1}'.format(_(self.status), self.subject)
 
-    def get_customer_details(self):
-        cust = frappe.db.sql("select customer_name from `tabCustomer` where name=%s", self.customer)
-        if cust:
-            ret = {'customer_name': cust and cust[0][0] or ''}
-            return ret
+	def get_customer_details(self):
+		cust = frappe.db.sql("select customer_name from `tabCustomer` where name=%s", self.customer)
+		if cust:
+			ret = {'customer_name': cust and cust[0][0] or ''}
+			return ret
 
-    def validate(self):
-        self.validate_dates()
-        self.validate_parent_expected_end_date()
-        self.validate_parent_project_dates()
-        self.validate_progress()
-        self.validate_status()
-        self.update_depends_on()
-        self.validate_dependencies_for_template_task()
+	def validate(self):
+		self.validate_dates()
+		self.validate_parent_expected_end_date()
+		self.validate_parent_project_dates()
+		self.validate_progress()
+		self.validate_status()
+		self.update_depends_on()
+		self.validate_dependencies_for_template_task()
 
-    def validate_dates(self):
-        if self.exp_start_date and self.exp_end_date and getdate(self.exp_start_date) > getdate(self.exp_end_date):
-            frappe.throw(_("{0} can not be greater than {1}").format(frappe.bold("Expected Start Date"), \
-                frappe.bold("Expected End Date")))
+	def validate_dates(self):
+		if self.exp_start_date and self.exp_end_date and getdate(self.exp_start_date) > getdate(self.exp_end_date):
+			frappe.throw(_("{0} can not be greater than {1}").format(frappe.bold("Expected Start Date"), \
+				frappe.bold("Expected End Date")))
 
-        if self.act_start_date and self.act_end_date and getdate(self.act_start_date) > getdate(self.act_end_date):
-            frappe.throw(_("{0} can not be greater than {1}").format(frappe.bold("Actual Start Date"), \
-                frappe.bold("Actual End Date")))
+		if self.act_start_date and self.act_end_date and getdate(self.act_start_date) > getdate(self.act_end_date):
+			frappe.throw(_("{0} can not be greater than {1}").format(frappe.bold("Actual Start Date"), \
+				frappe.bold("Actual End Date")))
 
-    def validate_parent_expected_end_date(self):
-        if self.parent_task:
-            parent_exp_end_date = frappe.db.get_value("Task", self.parent_task, "exp_end_date")
-            if parent_exp_end_date and getdate(self.get("exp_end_date")) > getdate(parent_exp_end_date):
-                frappe.throw(_("Expected End Date should be less than or equal to parent task's Expected End Date {0}.").format(getdate(parent_exp_end_date)))
+	def validate_parent_expected_end_date(self):
+		if self.parent_task:
+			parent_exp_end_date = frappe.db.get_value("Task", self.parent_task, "exp_end_date")
+			if parent_exp_end_date and getdate(self.get("exp_end_date")) > getdate(parent_exp_end_date):
+				frappe.throw(_("Expected End Date should be less than or equal to parent task's Expected End Date {0}.").format(getdate(parent_exp_end_date)))
 
-    def validate_parent_project_dates(self):
-        if not self.project or frappe.flags.in_test:
-            return
+	def validate_parent_project_dates(self):
+		if not self.project or frappe.flags.in_test:
+			return
 
-        expected_end_date = frappe.db.get_value("Project", self.project, "expected_end_date")
+		expected_end_date = frappe.db.get_value("Project", self.project, "expected_end_date")
 
-        if expected_end_date:
-            validate_project_dates(getdate(expected_end_date), self, "exp_start_date", "exp_end_date", "Expected")
-            validate_project_dates(getdate(expected_end_date), self, "act_start_date", "act_end_date", "Actual")
+		if expected_end_date:
+			validate_project_dates(getdate(expected_end_date), self, "exp_start_date", "exp_end_date", "Expected")
+			validate_project_dates(getdate(expected_end_date), self, "act_start_date", "act_end_date", "Actual")
 
-    def validate_status(self):
-        if self.is_template and self.status != "Template":
-            self.status = "Template"
-        if self.status!=self.get_db_value("status") and self.status == "Completed":
-            for d in self.depends_on:
-                if frappe.db.get_value("Task", d.task, "status") not in ("Completed", "Cancelled"):
-                    frappe.throw(_("Cannot complete task {0} as its dependant task {1} are not ccompleted / cancelled.").format(frappe.bold(self.name), frappe.bold(d.task)))
+	def validate_status(self):
+		if self.is_template and self.status != "Template":
+			self.status = "Template"
+		if self.status!=self.get_db_value("status") and self.status == "Completed":
+			for d in self.depends_on:
+				if frappe.db.get_value("Task", d.task, "status") not in ("Completed", "Cancelled"):
+					frappe.throw(_("Cannot complete task {0} as its dependant task {1} are not ccompleted / cancelled.").format(frappe.bold(self.name), frappe.bold(d.task)))
 
-            close_all_assignments(self.doctype, self.name)
+			close_all_assignments(self.doctype, self.name)
 
-    def validate_progress(self):
-        if flt(self.progress or 0) > 100:
-            frappe.throw(_("Progress % for a task cannot be more than 100."))
+	def validate_progress(self):
+		if flt(self.progress or 0) > 100:
+			frappe.throw(_("Progress % for a task cannot be more than 100."))
 
-        if flt(self.progress) == 100:
-            self.status = 'Completed'
+		if flt(self.progress) == 100:
+			self.status = 'Completed'
 
-        if self.status == 'Completed':
-            self.progress = 100
+		if self.status == 'Completed':
+			self.progress = 100
 
-    def validate_dependencies_for_template_task(self):
-        if self.is_template:
-            self.validate_parent_template_task()
-            self.validate_depends_on_tasks()
-        
-    def validate_parent_template_task(self):
-        if self.parent_task:
-            if not frappe.db.get_value("Task", self.parent_task, "is_template"):
-                parent_task_format = """<a href="#Form/Task/{0}">{0}</a>""".format(self.parent_task)
-                frappe.throw(_("Parent Task {0} is not a Template Task").format(parent_task_format))
-                
-    def validate_depends_on_tasks(self):
-        if self.depends_on:
-            for task in self.depends_on:
-                if not frappe.db.get_value("Task", task.task, "is_template"):
-                    dependent_task_format = """<a href="#Form/Task/{0}">{0}</a>""".format(task.task)
-                    frappe.throw(_("Dependent Task {0} is not a Template Task").format(dependent_task_format))
+	def validate_dependencies_for_template_task(self):
+		if self.is_template:
+			self.validate_parent_template_task()
+			self.validate_depends_on_tasks()
 
-    def update_depends_on(self):
-        depends_on_tasks = self.depends_on_tasks or ""
-        for d in self.depends_on:
-            if d.task and d.task not in depends_on_tasks:
-                depends_on_tasks += d.task + ","
-        self.depends_on_tasks = depends_on_tasks
+	def validate_parent_template_task(self):
+		if self.parent_task:
+			if not frappe.db.get_value("Task", self.parent_task, "is_template"):
+				parent_task_format = """<a href="#Form/Task/{0}">{0}</a>""".format(self.parent_task)
+				frappe.throw(_("Parent Task {0} is not a Template Task").format(parent_task_format))
 
-    def update_nsm_model(self):
-        frappe.utils.nestedset.update_nsm(self)
+	def validate_depends_on_tasks(self):
+		if self.depends_on:
+			for task in self.depends_on:
+				if not frappe.db.get_value("Task", task.task, "is_template"):
+					dependent_task_format = """<a href="#Form/Task/{0}">{0}</a>""".format(task.task)
+					frappe.throw(_("Dependent Task {0} is not a Template Task").format(dependent_task_format))
 
-    def on_update(self):
-        self.update_nsm_model()
-        self.check_recursion()
-        self.reschedule_dependent_tasks()
-        self.update_project()
-        self.unassign_todo()
-        self.populate_depends_on()
+	def update_depends_on(self):
+		depends_on_tasks = self.depends_on_tasks or ""
+		for d in self.depends_on:
+			if d.task and d.task not in depends_on_tasks:
+				depends_on_tasks += d.task + ","
+		self.depends_on_tasks = depends_on_tasks
 
-    def unassign_todo(self):
-        if self.status == "Completed":
-            close_all_assignments(self.doctype, self.name)
-        if self.status == "Cancelled":
-            clear(self.doctype, self.name)
+	def update_nsm_model(self):
+		frappe.utils.nestedset.update_nsm(self)
 
-    def update_total_expense_claim(self):
-        self.total_expense_claim = frappe.db.sql("""select sum(total_sanctioned_amount) from `tabExpense Claim`
-            where project = %s and task = %s and docstatus=1""",(self.project, self.name))[0][0]
+	def on_update(self):
+		self.update_nsm_model()
+		self.check_recursion()
+		self.reschedule_dependent_tasks()
+		self.update_project()
+		self.unassign_todo()
+		self.populate_depends_on()
 
-    def update_time_and_costing(self):
-        tl = frappe.db.sql("""select min(from_time) as start_date, max(to_time) as end_date,
-            sum(billing_amount) as total_billing_amount, sum(costing_amount) as total_costing_amount,
-            sum(hours) as time from `tabTimesheet Detail` where task = %s and docstatus=1"""
-            ,self.name, as_dict=1)[0]
-        if self.status == "Open":
-            self.status = "Working"
-        self.total_costing_amount= tl.total_costing_amount
-        self.total_billing_amount= tl.total_billing_amount
-        self.actual_time= tl.time
-        self.act_start_date= tl.start_date
-        self.act_end_date= tl.end_date
+	def unassign_todo(self):
+		if self.status == "Completed":
+			close_all_assignments(self.doctype, self.name)
+		if self.status == "Cancelled":
+			clear(self.doctype, self.name)
 
-    def update_project(self):
-        if self.project and not self.flags.from_project:
-            frappe.get_cached_doc("Project", self.project).update_project()
+	def update_total_expense_claim(self):
+		self.total_expense_claim = frappe.db.sql("""select sum(total_sanctioned_amount) from `tabExpense Claim`
+			where project = %s and task = %s and docstatus=1""",(self.project, self.name))[0][0]
 
-    def check_recursion(self):
-        if self.flags.ignore_recursion_check: return
-        check_list = [['task', 'parent'], ['parent', 'task']]
-        for d in check_list:
-            task_list, count = [self.name], 0
-            while (len(task_list) > count ):
-                tasks = frappe.db.sql(" select %s from `tabTask Depends On` where %s = %s " %
-                    (d[0], d[1], '%s'), cstr(task_list[count]))
-                count = count + 1
-                for b in tasks:
-                    if b[0] == self.name:
-                        frappe.throw(_("Circular Reference Error"), CircularReferenceError)
-                    if b[0]:
-                        task_list.append(b[0])
+	def update_time_and_costing(self):
+		tl = frappe.db.sql("""select min(from_time) as start_date, max(to_time) as end_date,
+			sum(billing_amount) as total_billing_amount, sum(costing_amount) as total_costing_amount,
+			sum(hours) as time from `tabTimesheet Detail` where task = %s and docstatus=1"""
+			,self.name, as_dict=1)[0]
+		if self.status == "Open":
+			self.status = "Working"
+		self.total_costing_amount= tl.total_costing_amount
+		self.total_billing_amount= tl.total_billing_amount
+		self.actual_time= tl.time
+		self.act_start_date= tl.start_date
+		self.act_end_date= tl.end_date
 
-                if count == 15:
-                    break
+	def update_project(self):
+		if self.project and not self.flags.from_project:
+			frappe.get_cached_doc("Project", self.project).update_project()
 
-    def reschedule_dependent_tasks(self):
-        end_date = self.exp_end_date or self.act_end_date
-        if end_date:
-            for task_name in frappe.db.sql("""
-                select name from `tabTask` as parent
-                where parent.project = %(project)s
-                    and parent.name in (
-                        select parent from `tabTask Depends On` as child
-                        where child.task = %(task)s and child.project = %(project)s)
-            """, {'project': self.project, 'task':self.name }, as_dict=1):
-                task = frappe.get_doc("Task", task_name.name)
-                if task.exp_start_date and task.exp_end_date and task.exp_start_date < getdate(end_date) and task.status == "Open":
-                    task_duration = date_diff(task.exp_end_date, task.exp_start_date)
-                    task.exp_start_date = add_days(end_date, 1)
-                    task.exp_end_date = add_days(task.exp_start_date, task_duration)
-                    task.flags.ignore_recursion_check = True
-                    task.save()
+	def check_recursion(self):
+		if self.flags.ignore_recursion_check: return
+		check_list = [['task', 'parent'], ['parent', 'task']]
+		for d in check_list:
+			task_list, count = [self.name], 0
+			while (len(task_list) > count ):
+				tasks = frappe.db.sql(" select %s from `tabTask Depends On` where %s = %s " %
+					(d[0], d[1], '%s'), cstr(task_list[count]))
+				count = count + 1
+				for b in tasks:
+					if b[0] == self.name:
+						frappe.throw(_("Circular Reference Error"), CircularReferenceError)
+					if b[0]:
+						task_list.append(b[0])
 
-    def has_webform_permission(self):
-        project_user = frappe.db.get_value("Project User", {"parent": self.project, "user":frappe.session.user} , "user")
-        if project_user:
-            return True
+				if count == 15:
+					break
 
-    def populate_depends_on(self):
-        if self.parent_task:
-            parent = frappe.get_doc('Task', self.parent_task)
-            if self.name not in [row.task for row in parent.depends_on]:
-                parent.append("depends_on", {
-                    "doctype": "Task Depends On",
-                    "task": self.name,
-                    "subject": self.subject
-                })
-                parent.save()
+	def reschedule_dependent_tasks(self):
+		end_date = self.exp_end_date or self.act_end_date
+		if end_date:
+			for task_name in frappe.db.sql("""
+				select name from `tabTask` as parent
+				where parent.project = %(project)s
+					and parent.name in (
+						select parent from `tabTask Depends On` as child
+						where child.task = %(task)s and child.project = %(project)s)
+			""", {'project': self.project, 'task':self.name }, as_dict=1):
+				task = frappe.get_doc("Task", task_name.name)
+				if task.exp_start_date and task.exp_end_date and task.exp_start_date < getdate(end_date) and task.status == "Open":
+					task_duration = date_diff(task.exp_end_date, task.exp_start_date)
+					task.exp_start_date = add_days(end_date, 1)
+					task.exp_end_date = add_days(task.exp_start_date, task_duration)
+					task.flags.ignore_recursion_check = True
+					task.save()
 
-    def on_trash(self):
-        if check_if_child_exists(self.name):
-            throw(_("Child Task exists for this Task. You can not delete this Task."))
+	def has_webform_permission(self):
+		project_user = frappe.db.get_value("Project User", {"parent": self.project, "user":frappe.session.user} , "user")
+		if project_user:
+			return True
 
-        self.update_nsm_model()
+	def populate_depends_on(self):
+		if self.parent_task:
+			parent = frappe.get_doc('Task', self.parent_task)
+			if self.name not in [row.task for row in parent.depends_on]:
+				parent.append("depends_on", {
+					"doctype": "Task Depends On",
+					"task": self.name,
+					"subject": self.subject
+				})
+				parent.save()
 
-    def after_delete(self):
-        self.update_project()
+	def on_trash(self):
+		if check_if_child_exists(self.name):
+			throw(_("Child Task exists for this Task. You can not delete this Task."))
 
-    def update_status(self):
-        if self.status not in ('Cancelled', 'Completed') and self.exp_end_date:
-            from datetime import datetime
-            if self.exp_end_date < datetime.now().date():
-                self.db_set('status', 'Overdue', update_modified=False)
-                self.update_project()
+		self.update_nsm_model()
+
+	def after_delete(self):
+		self.update_project()
+
+	def update_status(self):
+		if self.status not in ('Cancelled', 'Completed') and self.exp_end_date:
+			from datetime import datetime
+			if self.exp_end_date < datetime.now().date():
+				self.db_set('status', 'Overdue', update_modified=False)
+				self.update_project()
 
 @frappe.whitelist()
 def check_if_child_exists(name):
-    child_tasks = frappe.get_all("Task", filters={"parent_task": name})
-    child_tasks = [get_link_to_form("Task", task.name) for task in child_tasks]
-    return child_tasks
+	child_tasks = frappe.get_all("Task", filters={"parent_task": name})
+	child_tasks = [get_link_to_form("Task", task.name) for task in child_tasks]
+	return child_tasks
 
 
 @frappe.whitelist()
 @frappe.validate_and_sanitize_search_inputs
 def get_project(doctype, txt, searchfield, start, page_len, filters):
-    from erpnext.controllers.queries import get_match_cond
-    return frappe.db.sql(""" select name from `tabProject`
-            where %(key)s like %(txt)s
-                %(mcond)s
-            order by name
-            limit %(start)s, %(page_len)s""" % {
-                'key': searchfield,
-                'txt': frappe.db.escape('%' + txt + '%'),
-                'mcond':get_match_cond(doctype),
-                'start': start,
-                'page_len': page_len
-            })
+	from erpnext.controllers.queries import get_match_cond
+	meta = frappe.get_meta(doctype)
+	searchfields = meta.get_search_fields()
+	search_columns = ", " + ", ".join(searchfields) if searchfields else ''
+	search_cond = " or " + " or ".join([field + " like %(txt)s" for field in searchfields])
+
+	return frappe.db.sql(""" select name {search_columns} from `tabProject`
+		where %(key)s like %(txt)s
+			%(mcond)s
+			{search_condition}
+		order by name
+		limit %(start)s, %(page_len)s""".format(search_columns = search_columns,
+			search_condition=search_cond), {
+			'key': searchfield,
+			'txt': '%' + txt + '%',
+			'mcond':get_match_cond(doctype),
+			'start': start,
+			'page_len': page_len
+		})
 
 
 @frappe.whitelist()
 def set_multiple_status(names, status):
-    names = json.loads(names)
-    for name in names:
-        task = frappe.get_doc("Task", name)
-        task.status = status
-        task.save()
+	names = json.loads(names)
+	for name in names:
+		task = frappe.get_doc("Task", name)
+		task.status = status
+		task.save()
 
 def set_tasks_as_overdue():
-    tasks = frappe.get_all("Task", filters={"status": ["not in", ["Cancelled", "Completed"]]}, fields=["name", "status", "review_date"])
-    for task in tasks:
-        if task.status == "Pending Review":
-            if getdate(task.review_date) > getdate(today()):
-                continue
-        frappe.get_doc("Task", task.name).update_status()
+	tasks = frappe.get_all("Task", filters={"status": ["not in", ["Cancelled", "Completed"]]}, fields=["name", "status", "review_date"])
+	for task in tasks:
+		if task.status == "Pending Review":
+			if getdate(task.review_date) > getdate(today()):
+				continue
+		frappe.get_doc("Task", task.name).update_status()
 
 
 @frappe.whitelist()
 def make_timesheet(source_name, target_doc=None, ignore_permissions=False):
-    def set_missing_values(source, target):
-        target.append("time_logs", {
-            "hours": source.actual_time,
-            "completed": source.status == "Completed",
-            "project": source.project,
-            "task": source.name
-        })
+	def set_missing_values(source, target):
+		target.append("time_logs", {
+			"hours": source.actual_time,
+			"completed": source.status == "Completed",
+			"project": source.project,
+			"task": source.name
+		})
 
-    doclist = get_mapped_doc("Task", source_name, {
-            "Task": {
-                "doctype": "Timesheet"
-            }
-        }, target_doc, postprocess=set_missing_values, ignore_permissions=ignore_permissions)
+	doclist = get_mapped_doc("Task", source_name, {
+			"Task": {
+				"doctype": "Timesheet"
+			}
+		}, target_doc, postprocess=set_missing_values, ignore_permissions=ignore_permissions)
 
-    return doclist
+	return doclist
 
 
 @frappe.whitelist()
 def get_children(doctype, parent, task=None, project=None, is_root=False):
 
-    filters = [['docstatus', '<', '2']]
+	filters = [['docstatus', '<', '2']]
 
-    if task:
-        filters.append(['parent_task', '=', task])
-    elif parent and not is_root:
-        # via expand child
-        filters.append(['parent_task', '=', parent])
-    else:
-        filters.append(['ifnull(`parent_task`, "")', '=', ''])
+	if task:
+		filters.append(['parent_task', '=', task])
+	elif parent and not is_root:
+		# via expand child
+		filters.append(['parent_task', '=', parent])
+	else:
+		filters.append(['ifnull(`parent_task`, "")', '=', ''])
 
-    if project:
-        filters.append(['project', '=', project])
+	if project:
+		filters.append(['project', '=', project])
 
-    tasks = frappe.get_list(doctype, fields=[
-        'name as value',
-        'subject as title',
-        'is_group as expandable'
-    ], filters=filters, order_by='name')
+	tasks = frappe.get_list(doctype, fields=[
+		'name as value',
+		'subject as title',
+		'is_group as expandable'
+	], filters=filters, order_by='name')
 
-    # return tasks
-    return tasks
+	# return tasks
+	return tasks
 
 @frappe.whitelist()
 def add_node():
-    from frappe.desk.treeview import make_tree_args
-    args = frappe.form_dict
-    args.update({
-        "name_field": "subject"
-    })
-    args = make_tree_args(**args)
+	from frappe.desk.treeview import make_tree_args
+	args = frappe.form_dict
+	args.update({
+		"name_field": "subject"
+	})
+	args = make_tree_args(**args)
 
-    if args.parent_task == 'All Tasks' or args.parent_task == args.project:
-        args.parent_task = None
+	if args.parent_task == 'All Tasks' or args.parent_task == args.project:
+		args.parent_task = None
 
-    frappe.get_doc(args).insert()
+	frappe.get_doc(args).insert()
 
 @frappe.whitelist()
 def add_multiple_tasks(data, parent):
-    data = json.loads(data)
-    new_doc = {'doctype': 'Task', 'parent_task': parent if parent!="All Tasks" else ""}
-    new_doc['project'] = frappe.db.get_value('Task', {"name": parent}, 'project') or ""
+	data = json.loads(data)
+	new_doc = {'doctype': 'Task', 'parent_task': parent if parent!="All Tasks" else ""}
+	new_doc['project'] = frappe.db.get_value('Task', {"name": parent}, 'project') or ""
 
-    for d in data:
-        if not d.get("subject"): continue
-        new_doc['subject'] = d.get("subject")
-        new_task = frappe.get_doc(new_doc)
-        new_task.insert()
+	for d in data:
+		if not d.get("subject"): continue
+		new_doc['subject'] = d.get("subject")
+		new_task = frappe.get_doc(new_doc)
+		new_task.insert()
 
 def on_doctype_update():
-    frappe.db.add_index("Task", ["lft", "rgt"])
+	frappe.db.add_index("Task", ["lft", "rgt"])
 
 def validate_project_dates(project_end_date, task, task_start, task_end, actual_or_expected_date):
-    if task.get(task_start) and date_diff(project_end_date, getdate(task.get(task_start))) < 0:
-        frappe.throw(_("Task's {0} Start Date cannot be after Project's End Date.").format(actual_or_expected_date))
+	if task.get(task_start) and date_diff(project_end_date, getdate(task.get(task_start))) < 0:
+		frappe.throw(_("Task's {0} Start Date cannot be after Project's End Date.").format(actual_or_expected_date))
 
-    if task.get(task_end) and date_diff(project_end_date, getdate(task.get(task_end))) < 0:
-        frappe.throw(_("Task's {0} End Date cannot be after Project's End Date.").format(actual_or_expected_date))
+	if task.get(task_end) and date_diff(project_end_date, getdate(task.get(task_end))) < 0:
+		frappe.throw(_("Task's {0} End Date cannot be after Project's End Date.").format(actual_or_expected_date))
diff --git a/erpnext/projects/doctype/timesheet/timesheet.py b/erpnext/projects/doctype/timesheet/timesheet.py
index ea81b3e..ed02f79 100644
--- a/erpnext/projects/doctype/timesheet/timesheet.py
+++ b/erpnext/projects/doctype/timesheet/timesheet.py
@@ -204,14 +204,16 @@
 			ts_detail.billing_rate = 0.0
 
 @frappe.whitelist()
-def get_projectwise_timesheet_data(project, parent=None):
-	cond = ''
+def get_projectwise_timesheet_data(project, parent=None, from_time=None, to_time=None):
+	condition = ''
 	if parent:
-		cond = "and parent = %(parent)s"
+		condition = "AND parent = %(parent)s"
+	if from_time and to_time:
+		condition += "AND from_time BETWEEN %(from_time)s AND %(to_time)s"
 
 	return frappe.db.sql("""select name, parent, billing_hours, billing_amount as billing_amt
 			from `tabTimesheet Detail` where parenttype = 'Timesheet' and docstatus=1 and project = %(project)s {0} and billable = 1
-			and sales_invoice is null""".format(cond), {'project': project, 'parent': parent}, as_dict=1)
+			and sales_invoice is null""".format(condition), {'project': project, 'parent': parent, 'from_time': from_time, 'to_time': to_time}, as_dict=1)
 
 @frappe.whitelist()
 @frappe.validate_and_sanitize_search_inputs
diff --git a/erpnext/quality_management/doctype/non_conformance/non_conformance.json b/erpnext/quality_management/doctype/non_conformance/non_conformance.json
index bfeb96b..8dfe2d6 100644
--- a/erpnext/quality_management/doctype/non_conformance/non_conformance.json
+++ b/erpnext/quality_management/doctype/non_conformance/non_conformance.json
@@ -70,18 +70,18 @@
   },
   {
    "fieldname": "corrective_action",
-   "fieldtype": "Text",
+   "fieldtype": "Text Editor",
    "label": "Corrective Action"
   },
   {
    "fieldname": "preventive_action",
-   "fieldtype": "Text",
+   "fieldtype": "Text Editor",
    "label": "Preventive Action"
   }
  ],
  "index_web_pages_for_search": 1,
  "links": [],
- "modified": "2020-10-26 15:27:47.247814",
+ "modified": "2021-02-26 15:27:47.247814",
  "modified_by": "Administrator",
  "module": "Quality Management",
  "name": "Non Conformance",
@@ -115,4 +115,4 @@
  "sort_field": "modified",
  "sort_order": "DESC",
  "track_changes": 1
-}
\ No newline at end of file
+}
diff --git a/erpnext/regional/india/e_invoice/utils.py b/erpnext/regional/india/e_invoice/utils.py
index eea85cd..96f7f1b 100644
--- a/erpnext/regional/india/e_invoice/utils.py
+++ b/erpnext/regional/india/e_invoice/utils.py
@@ -202,9 +202,11 @@
 		item[attr] = 0
 
 	for t in invoice.taxes:
-		# this contains item wise tax rate & tax amount (incl. discount)
-		item_tax_detail = json.loads(t.item_wise_tax_detail).get(item.item_code)
-		if t.account_head in gst_accounts_list:
+		is_applicable = t.tax_amount and t.account_head in gst_accounts_list
+		if is_applicable:
+			# this contains item wise tax rate & tax amount (incl. discount)
+			item_tax_detail = json.loads(t.item_wise_tax_detail).get(item.item_code)
+
 			item_tax_rate = item_tax_detail[0]
 			# item tax amount excluding discount amount
 			item_tax_amount = (item_tax_rate / 100) * item.base_net_amount
@@ -229,7 +231,7 @@
 
 	if invoice.apply_discount_on == 'Net Total' and invoice.discount_amount:
 		invoice_value_details.base_total = abs(invoice.base_total)
-		invoice_value_details.invoice_discount_amt = invoice.base_discount_amount
+		invoice_value_details.invoice_discount_amt = abs(invoice.base_discount_amount)
 	else:
 		invoice_value_details.base_total = abs(invoice.base_net_total)
 		# since tax already considers discount amount
diff --git a/erpnext/selling/doctype/customer/customer.json b/erpnext/selling/doctype/customer/customer.json
index a048928..7d5e84d 100644
--- a/erpnext/selling/doctype/customer/customer.json
+++ b/erpnext/selling/doctype/customer/customer.json
@@ -212,8 +212,7 @@
    "fieldtype": "Link",
    "ignore_user_permissions": 1,
    "label": "Represents Company",
-   "options": "Company",
-   "unique": 1
+   "options": "Company"
   },
   {
    "depends_on": "represents_company",
@@ -500,7 +499,7 @@
  "image_field": "image",
  "index_web_pages_for_search": 1,
  "links": [],
- "modified": "2021-01-27 12:54:57.258959",
+ "modified": "2021-01-28 12:54:57.258959",
  "modified_by": "Administrator",
  "module": "Selling",
  "name": "Customer",
diff --git a/erpnext/selling/page/point_of_sale/pos_controller.js b/erpnext/selling/page/point_of_sale/pos_controller.js
index 338a3cc..74b4bb0 100644
--- a/erpnext/selling/page/point_of_sale/pos_controller.js
+++ b/erpnext/selling/page/point_of_sale/pos_controller.js
@@ -498,10 +498,11 @@
 
 	async on_cart_update(args) {
 		frappe.dom.freeze();
+		let item_row = undefined;
 		try {
 			let { field, value, item } = args;
 			const { item_code, batch_no, serial_no, uom } = item;
-			let item_row = this.get_item_from_frm(item_code, batch_no, uom);
+			item_row = this.get_item_from_frm(item_code, batch_no, uom);
 
 			const item_selected_from_selector = field === 'qty' && value === "+1"
 
@@ -553,10 +554,12 @@
 				this.check_serial_batch_selection_needed(item_row) && this.edit_item_details_of(item_row);
 				this.update_cart_html(item_row);
 			}
+
 		} catch (error) {
 			console.log(error);
 		} finally {
 			frappe.dom.unfreeze();
+			return item_row;
 		}
 	}
 
diff --git a/erpnext/selling/page/point_of_sale/pos_item_cart.js b/erpnext/selling/page/point_of_sale/pos_item_cart.js
index 044e803..9ab9eef 100644
--- a/erpnext/selling/page/point_of_sale/pos_item_cart.js
+++ b/erpnext/selling/page/point_of_sale/pos_item_cart.js
@@ -472,7 +472,8 @@
 		if (!frm) frm = this.events.get_frm();
 
 		this.render_net_total(frm.doc.net_total);
-		this.render_grand_total(frm.doc.grand_total);
+		const grand_total = cint(frappe.sys_defaults.disable_rounded_total) ? frm.doc.grand_total : frm.doc.rounded_total;
+		this.render_grand_total(grand_total);
 
 		const taxes = frm.doc.taxes.map(t => {
 			return {
diff --git a/erpnext/selling/page/point_of_sale/pos_item_selector.js b/erpnext/selling/page/point_of_sale/pos_item_selector.js
index 7c116e9..e0d5b73 100644
--- a/erpnext/selling/page/point_of_sale/pos_item_selector.js
+++ b/erpnext/selling/page/point_of_sale/pos_item_selector.js
@@ -152,6 +152,10 @@
 		this.item_group_field.toggle_label(false);
 	}
 
+	set_search_value(value) {
+		$(this.search_field.$input[0]).val(value).trigger("input");
+	}
+
 	bind_events() {
 		const me = this;
 		window.onScan = onScan;
@@ -159,7 +163,7 @@
 			onScan: (sScancode) => {
 				if (this.search_field && this.$component.is(':visible')) {
 					this.search_field.set_focus();
-					$(this.search_field.$input[0]).val(sScancode).trigger("input");
+					this.set_search_value(sScancode);
 					this.barcode_scanned = true;
 				}
 			}
@@ -178,6 +182,7 @@
 			uom = uom === "undefined" ? undefined : uom;
 
 			me.events.item_selected({ field: 'qty', value: "+1", item: { item_code, batch_no, serial_no, uom }});
+			me.set_search_value('');
 		});
 
 		this.search_field.$input.on('input', (e) => {
diff --git a/erpnext/selling/page/point_of_sale/pos_payment.js b/erpnext/selling/page/point_of_sale/pos_payment.js
index bcbac3b..22a279d 100644
--- a/erpnext/selling/page/point_of_sale/pos_payment.js
+++ b/erpnext/selling/page/point_of_sale/pos_payment.js
@@ -223,7 +223,8 @@
 
 			if (success) {
 				title = __("Payment Received");
-				if (amount >= doc.grand_total) {
+				const grand_total = cint(frappe.sys_defaults.disable_rounded_total) ? doc.grand_total : doc.rounded_total;
+				if (amount >= grand_total) {
 					frappe.dom.unfreeze();
 					message = __("Payment of {0} received successfully.", [format_currency(amount, doc.currency, 0)]);
 					this.events.submit_invoice();
@@ -243,7 +244,8 @@
 
 	auto_set_remaining_amount() {
 		const doc = this.events.get_frm().doc;
-		const remaining_amount = doc.grand_total - doc.paid_amount;
+		const grand_total = cint(frappe.sys_defaults.disable_rounded_total) ? doc.grand_total : doc.rounded_total;
+		const remaining_amount = grand_total - doc.paid_amount;
 		const current_value = this.selected_mode ? this.selected_mode.get_value() : undefined;
 		if (!current_value && remaining_amount > 0 && this.selected_mode) {
 			this.selected_mode.set_value(remaining_amount);
@@ -389,7 +391,7 @@
 	}
 
 	attach_cash_shortcuts(doc) {
-		const grand_total = doc.grand_total;
+		const grand_total = cint(frappe.sys_defaults.disable_rounded_total) ? doc.grand_total : doc.rounded_total;
 		const currency = doc.currency;
 
 		const shortcuts = this.get_cash_shortcuts(flt(grand_total));
@@ -499,7 +501,8 @@
 	update_totals_section(doc) {
 		if (!doc) doc = this.events.get_frm().doc;
 		const paid_amount = doc.paid_amount;
-		const remaining = doc.grand_total - doc.paid_amount;
+		const grand_total = cint(frappe.sys_defaults.disable_rounded_total) ? doc.grand_total : doc.rounded_total;
+		const remaining = grand_total - doc.paid_amount;
 		const change = doc.change_amount || remaining <= 0 ? -1 * remaining : undefined;
 		const currency = doc.currency;
 		const label = change ? __('Change') : __('To Be Paid');
@@ -507,7 +510,7 @@
 		this.$totals.html(
 			`<div class="col">
 				<div class="total-label">Grand Total</div>
-				<div class="value">${format_currency(doc.grand_total, currency)}</div>
+				<div class="value">${format_currency(grand_total, currency)}</div>
 			</div>
 			<div class="seperator-y"></div>
 			<div class="col">
diff --git a/erpnext/setup/doctype/company/company.js b/erpnext/setup/doctype/company/company.js
index 36033d9..c041d26 100644
--- a/erpnext/setup/doctype/company/company.js
+++ b/erpnext/setup/doctype/company/company.js
@@ -140,7 +140,7 @@
 			doc: frm.doc,
 			freeze: true,
 			callback: function() {
-				frappe.msgprint(__("Default tax templates for sales and purchase are created."));
+				frappe.msgprint(__("Default tax templates for sales, purchase and items are created."));
 			}
 		})
 	},
diff --git a/erpnext/setup/setup_wizard/operations/taxes_setup.py b/erpnext/setup/setup_wizard/operations/taxes_setup.py
index e66fa76..c3c1593 100644
--- a/erpnext/setup/setup_wizard/operations/taxes_setup.py
+++ b/erpnext/setup/setup_wizard/operations/taxes_setup.py
@@ -29,6 +29,7 @@
 	try:
 		if accounts:
 			make_sales_and_purchase_tax_templates(accounts, template_name)
+			make_item_tax_templates(accounts, template_name)
 	except frappe.NameError:
 		if frappe.message_log: frappe.message_log.pop()
 	except RootNotEditable:
@@ -84,6 +85,27 @@
 	doc = frappe.get_doc(purchase_tax_template)
 	doc.insert(ignore_permissions=True)
 
+def make_item_tax_templates(accounts, template_name=None):
+	if not template_name:
+		template_name = accounts[0].name
+
+	item_tax_template = {
+		"doctype": "Item Tax Template",
+		"title": template_name,
+		"company": accounts[0].company,
+		'taxes': []
+	}
+
+
+	for account in accounts:
+		item_tax_template['taxes'].append({
+			"tax_type": account.name,
+			"tax_rate": account.tax_rate
+		})
+
+	# Items
+	frappe.get_doc(copy.deepcopy(item_tax_template)).insert(ignore_permissions=True)
+
 def get_tax_account_group(company):
 	tax_group = frappe.db.get_value("Account",
 		{"account_name": "Duties and Taxes", "is_group": 1, "company": company})
diff --git a/erpnext/stock/__init__.py b/erpnext/stock/__init__.py
index 9e240cc..283f7d5 100644
--- a/erpnext/stock/__init__.py
+++ b/erpnext/stock/__init__.py
@@ -38,7 +38,7 @@
 			frappe.flags.warehouse_account_map[company] = warehouse_account
 		else:
 			frappe.flags.warehouse_account_map = warehouse_account
-	
+
 	return frappe.flags.warehouse_account_map.get(company) or frappe.flags.warehouse_account_map
 
 def get_warehouse_account(warehouse, warehouse_account=None):
@@ -64,6 +64,10 @@
 	if not account and warehouse.company:
 		account = get_company_default_inventory_account(warehouse.company)
 
+	if not account and warehouse.company:
+		account = frappe.db.get_value('Account',
+			{'account_type': 'Stock', 'is_group': 0, 'company': warehouse.company}, 'name')
+
 	if not account and warehouse.company and not warehouse.is_group:
 		frappe.throw(_("Please set Account in Warehouse {0} or Default Inventory Account in Company {1}")
 			.format(warehouse.name, warehouse.company))
diff --git a/erpnext/stock/doctype/batch/batch.py b/erpnext/stock/doctype/batch/batch.py
index c8424f1..8fdda56 100644
--- a/erpnext/stock/doctype/batch/batch.py
+++ b/erpnext/stock/doctype/batch/batch.py
@@ -93,7 +93,7 @@
 
 			if create_new_batch:
 				if batch_number_series:
-					self.batch_id = make_autoname(batch_number_series)
+					self.batch_id = make_autoname(batch_number_series, doc=self)
 				elif batch_uses_naming_series():
 					self.batch_id = self.get_name_from_naming_series()
 				else:
diff --git a/erpnext/stock/doctype/item/item.json b/erpnext/stock/doctype/item/item.json
index fcf7c26..6886c1b 100644
--- a/erpnext/stock/doctype/item/item.json
+++ b/erpnext/stock/doctype/item/item.json
@@ -521,8 +521,7 @@
    "fieldname": "has_variants",
    "fieldtype": "Check",
    "in_standard_filter": 1,
-   "label": "Has Variants",
-   "no_copy": 1
+   "label": "Has Variants"
   },
   {
    "default": "Item Attribute",
@@ -538,7 +537,6 @@
    "fieldtype": "Table",
    "hidden": 1,
    "label": "Attributes",
-   "no_copy": 1,
    "options": "Item Variant Attribute"
   },
   {
@@ -1068,7 +1066,7 @@
  "index_web_pages_for_search": 1,
  "links": [],
  "max_attachments": 1,
- "modified": "2021-01-25 20:49:50.222976",
+ "modified": "2021-02-18 14:00:19.668049",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Item",
diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
index d721014..70687bda 100644
--- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
+++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
@@ -324,10 +324,12 @@
 						else:
 							loss_account = self.get_company_default("default_expense_account")
 
+						cost_center = d.cost_center or frappe.get_cached_value("Company", self.company, "cost_center")
+
 						gl_entries.append(self.get_gl_dict({
 							"account": loss_account,
 							"against": warehouse_account[d.warehouse]["account"],
-							"cost_center": d.cost_center,
+							"cost_center": cost_center,
 							"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
 							"debit": divisional_loss,
 							"project": d.project
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py
index 9cdc3cf..ea1b387 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.py
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.py
@@ -276,9 +276,10 @@
 					item_wise_qty.setdefault(d.item_code, []).append(d.qty)
 
 		for item_code, qty_list in iteritems(item_wise_qty):
-			if self.fg_completed_qty != sum(qty_list):
+			total = flt(sum(qty_list), frappe.get_precision("Stock Entry Detail", "qty"))
+			if self.fg_completed_qty != total:
 				frappe.throw(_("The finished product {0} quantity {1} and For Quantity {2} cannot be different")
-					.format(frappe.bold(item_code), frappe.bold(sum(qty_list)), frappe.bold(self.fg_completed_qty)))
+					.format(frappe.bold(item_code), frappe.bold(total), frappe.bold(self.fg_completed_qty)))
 
 	def validate_difference_account(self):
 		if not cint(erpnext.is_perpetual_inventory_enabled(self.company)):