Merge branch 'develop' into loan_manager_amend
diff --git a/.github/workflows/ci-tests.yml b/.github/workflows/ci-tests.yml
index 78c2f5a..824b74e 100644
--- a/.github/workflows/ci-tests.yml
+++ b/.github/workflows/ci-tests.yml
@@ -85,10 +85,9 @@
         run: |
           cp ~/frappe-bench/sites/.coverage ${GITHUB_WORKSPACE}
           cd ${GITHUB_WORKSPACE}
-          pip install coveralls==2.2.0
-          pip install coverage==4.5.4
-          coveralls
+          pip install coveralls==3.0.1
+          pip install coverage==5.5
+          coveralls --service=github
         env:
           GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
           COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_TOKEN }}
-
diff --git a/erpnext/accounts/doctype/accounts_settings/accounts_settings.json b/erpnext/accounts/doctype/accounts_settings/accounts_settings.json
index a3c29b6..e1276e7 100644
--- a/erpnext/accounts/doctype/accounts_settings/accounts_settings.json
+++ b/erpnext/accounts/doctype/accounts_settings/accounts_settings.json
@@ -12,6 +12,7 @@
   "frozen_accounts_modifier",
   "determine_address_tax_category_from",
   "over_billing_allowance",
+  "role_allowed_to_over_bill",
   "column_break_4",
   "credit_controller",
   "check_supplier_invoice_uniqueness",
@@ -226,6 +227,13 @@
    "fieldname": "delete_linked_ledger_entries",
    "fieldtype": "Check",
    "label": "Delete Accounting and Stock Ledger Entries on deletion of Transaction"
+  },
+  {
+   "description": "Users with this role are allowed to over bill above the allowance percentage",
+   "fieldname": "role_allowed_to_over_bill",
+   "fieldtype": "Link",
+   "label": "Role Allowed to Over Bill ",
+   "options": "Role"
   }
  ],
  "icon": "icon-cog",
@@ -233,7 +241,7 @@
  "index_web_pages_for_search": 1,
  "issingle": 1,
  "links": [],
- "modified": "2021-01-05 13:04:00.118892",
+ "modified": "2021-03-11 18:52:05.601996",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "Accounts Settings",
diff --git a/erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry.py b/erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry.py
index a05e598..949211d 100644
--- a/erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry.py
+++ b/erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry.py
@@ -89,8 +89,8 @@
 @frappe.whitelist()
 @frappe.validate_and_sanitize_search_inputs
 def get_cashiers(doctype, txt, searchfield, start, page_len, filters):
-	cashiers_list = frappe.get_all("POS Profile User", filters=filters, fields=['user'])
-	return [c['user'] for c in cashiers_list]
+	cashiers_list = frappe.get_all("POS Profile User", filters=filters, fields=['user'], as_list=1)
+	return [c for c in cashiers_list]
 
 @frappe.whitelist()
 def get_pos_invoices(start, end, pos_profile, user):
diff --git a/erpnext/accounts/doctype/pricing_rule/utils.py b/erpnext/accounts/doctype/pricing_rule/utils.py
index b91a7a5..d23b952 100644
--- a/erpnext/accounts/doctype/pricing_rule/utils.py
+++ b/erpnext/accounts/doctype/pricing_rule/utils.py
@@ -173,7 +173,7 @@
 		if parenttype in ["Customer Group", "Item Group", "Territory"]:
 			parent_field = "parent_{0}".format(frappe.scrub(parenttype))
 			root_name = frappe.db.get_list(parenttype,
-				{"is_group": 1, parent_field: ("is", "not set")}, "name", as_list=1)
+				{"is_group": 1, parent_field: ("is", "not set")}, "name", as_list=1, ignore_permissions=True)
 
 			if root_name and root_name[0][0]:
 				parent_groups.append(root_name[0][0])
diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py
index 33fbf1c..d36e7b0 100644
--- a/erpnext/controllers/accounts_controller.py
+++ b/erpnext/controllers/accounts_controller.py
@@ -717,7 +717,9 @@
 						total_billed_amt = abs(total_billed_amt)
 						max_allowed_amt = abs(max_allowed_amt)
 
-					if total_billed_amt - max_allowed_amt > 0.01:
+					role_allowed_to_over_bill = frappe.db.get_single_value('Accounts Settings', 'role_allowed_to_over_bill')
+
+					if total_billed_amt - max_allowed_amt > 0.01 and role_allowed_to_over_bill not in frappe.get_roles():
 						frappe.throw(_("Cannot overbill for Item {0} in row {1} more than {2}. To allow over-billing, please set allowance in Accounts Settings")
 							.format(item.item_code, item.idx, max_allowed_amt))
 
diff --git a/erpnext/controllers/status_updater.py b/erpnext/controllers/status_updater.py
index cdb6d24..5276da9 100644
--- a/erpnext/controllers/status_updater.py
+++ b/erpnext/controllers/status_updater.py
@@ -201,10 +201,14 @@
 			get_allowance_for(item['item_code'], self.item_allowance,
 				self.global_qty_allowance, self.global_amount_allowance, qty_or_amount)
 
-		overflow_percent = ((item[args['target_field']] - item[args['target_ref_field']]) /
-		 	item[args['target_ref_field']]) * 100
+		role_allowed_to_over_deliver_receive = frappe.db.get_single_value('Stock Settings', 'role_allowed_to_over_deliver_receive')
+		role_allowed_to_over_bill = frappe.db.get_single_value('Accounts Settings', 'role_allowed_to_over_bill')
+		role = role_allowed_to_over_deliver_receive if qty_or_amount == 'qty' else role_allowed_to_over_bill
 
-		if overflow_percent - allowance > 0.01:
+		overflow_percent = ((item[args['target_field']] - item[args['target_ref_field']]) /
+			item[args['target_ref_field']]) * 100
+
+		if overflow_percent - allowance > 0.01 and role not in frappe.get_roles():
 			item['max_allowed'] = flt(item[args['target_ref_field']] * (100+allowance)/100)
 			item['reduce_by'] = item[args['target_field']] - item['max_allowed']
 
diff --git a/erpnext/healthcare/doctype/inpatient_occupancy/inpatient_occupancy.json b/erpnext/healthcare/doctype/inpatient_occupancy/inpatient_occupancy.json
index 818f125..3fa98b6 100644
--- a/erpnext/healthcare/doctype/inpatient_occupancy/inpatient_occupancy.json
+++ b/erpnext/healthcare/doctype/inpatient_occupancy/inpatient_occupancy.json
@@ -1,206 +1,64 @@
 {
- "allow_copy": 0, 
- "allow_events_in_timeline": 0, 
- "allow_guest_to_view": 0, 
- "allow_import": 0, 
- "allow_rename": 0, 
- "beta": 0, 
- "creation": "2018-07-12 12:07:36.932333", 
- "custom": 0, 
- "docstatus": 0, 
- "doctype": "DocType", 
- "document_type": "", 
- "editable_grid": 1, 
- "engine": "InnoDB", 
+ "actions": [],
+ "creation": "2018-07-12 12:07:36.932333",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "service_unit",
+  "check_in",
+  "left",
+  "check_out",
+  "invoiced"
+ ],
  "fields": [
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "service_unit", 
-   "fieldtype": "Link", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Healthcare Service Unit", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Healthcare Service Unit", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 1, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 1, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "service_unit",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "label": "Healthcare Service Unit",
+   "options": "Healthcare Service Unit",
+   "reqd": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "check_in", 
-   "fieldtype": "Datetime", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Check In", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 1, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "check_in",
+   "fieldtype": "Datetime",
+   "in_list_view": 1,
+   "label": "Check In"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "left", 
-   "fieldtype": "Check", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Left", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 1, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 1, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "default": "0",
+   "fieldname": "left",
+   "fieldtype": "Check",
+   "label": "Left",
+   "read_only": 1,
+   "search_index": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "check_out", 
-   "fieldtype": "Datetime", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Check Out", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 1, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "check_out",
+   "fieldtype": "Datetime",
+   "label": "Check Out"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "default": "0", 
-   "fieldname": "invoiced", 
-   "fieldtype": "Check", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Invoiced", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 1, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
+   "default": "0",
+   "fieldname": "invoiced",
+   "fieldtype": "Check",
+   "label": "Invoiced",
+   "read_only": 1
   }
- ], 
- "has_web_view": 0, 
- "hide_heading": 0, 
- "hide_toolbar": 0, 
- "idx": 0, 
- "image_view": 0, 
- "in_create": 0, 
- "is_submittable": 0, 
- "issingle": 0, 
- "istable": 1, 
- "max_attachments": 0, 
- "modified": "2018-11-04 03:33:26.958713", 
- "modified_by": "Administrator", 
- "module": "Healthcare", 
- "name": "Inpatient Occupancy", 
- "name_case": "", 
- "owner": "Administrator", 
- "permissions": [], 
- "quick_entry": 1, 
- "read_only": 0, 
- "read_only_onload": 0, 
- "restrict_to_domain": "Healthcare", 
- "show_name_in_global_search": 0, 
- "sort_field": "modified", 
- "sort_order": "DESC", 
- "track_changes": 1, 
- "track_seen": 0, 
- "track_views": 0
+ ],
+ "index_web_pages_for_search": 1,
+ "istable": 1,
+ "links": [],
+ "modified": "2021-03-18 15:08:54.634132",
+ "modified_by": "Administrator",
+ "module": "Healthcare",
+ "name": "Inpatient Occupancy",
+ "owner": "Administrator",
+ "permissions": [],
+ "quick_entry": 1,
+ "restrict_to_domain": "Healthcare",
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
 }
\ No newline at end of file
diff --git a/erpnext/healthcare/doctype/inpatient_record/inpatient_record.json b/erpnext/healthcare/doctype/inpatient_record/inpatient_record.json
index aaf0e85..0e1c2ba 100644
--- a/erpnext/healthcare/doctype/inpatient_record/inpatient_record.json
+++ b/erpnext/healthcare/doctype/inpatient_record/inpatient_record.json
@@ -185,7 +185,7 @@
    "fieldtype": "Datetime",
    "in_list_view": 1,
    "label": "Admitted Datetime",
-   "read_only": 1
+   "permlevel": 2
   },
   {
    "depends_on": "eval:(doc.expected_length_of_stay > 0)",
@@ -312,7 +312,7 @@
    "fieldname": "inpatient_occupancies",
    "fieldtype": "Table",
    "options": "Inpatient Occupancy",
-   "read_only": 1
+   "permlevel": 2
   },
   {
    "fieldname": "btn_transfer",
@@ -407,12 +407,12 @@
    "fieldname": "discharge_datetime",
    "fieldtype": "Datetime",
    "label": "Discharge Date",
-   "read_only": 1
+   "permlevel": 2
   }
  ],
  "index_web_pages_for_search": 1,
  "links": [],
- "modified": "2021-03-18 14:44:11.689956",
+ "modified": "2021-03-18 15:59:17.318988",
  "modified_by": "Administrator",
  "module": "Healthcare",
  "name": "Inpatient Record",
@@ -465,6 +465,37 @@
    "read": 1,
    "report": 1,
    "role": "Nursing User"
+  },
+  {
+   "email": 1,
+   "export": 1,
+   "permlevel": 2,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "Healthcare Administrator",
+   "share": 1,
+   "write": 1
+  },
+  {
+   "email": 1,
+   "export": 1,
+   "permlevel": 2,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "Physician",
+   "share": 1
+  },
+  {
+   "email": 1,
+   "export": 1,
+   "permlevel": 2,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "Nursing User",
+   "share": 1
   }
  ],
  "restrict_to_domain": "Healthcare",
diff --git a/erpnext/hr/doctype/compensatory_leave_request/compensatory_leave_request.py b/erpnext/hr/doctype/compensatory_leave_request/compensatory_leave_request.py
index aa5a67f..a6fe429 100644
--- a/erpnext/hr/doctype/compensatory_leave_request/compensatory_leave_request.py
+++ b/erpnext/hr/doctype/compensatory_leave_request/compensatory_leave_request.py
@@ -66,7 +66,7 @@
 
 			else:
 				leave_allocation = self.create_leave_allocation(leave_period, date_difference)
-			self.leave_allocation=leave_allocation.name
+			self.db_set("leave_allocation", leave_allocation.name)
 		else:
 			frappe.throw(_("There is no leave period in between {0} and {1}").format(format_date(self.work_from_date), format_date(self.work_end_date)))
 
@@ -124,4 +124,4 @@
 		))
 		allocation.insert(ignore_permissions=True)
 		allocation.submit()
-		return allocation
\ No newline at end of file
+		return allocation
diff --git a/erpnext/payroll/doctype/payroll_entry/payroll_entry.js b/erpnext/payroll/doctype/payroll_entry/payroll_entry.js
index 85bb651..f289260 100644
--- a/erpnext/payroll/doctype/payroll_entry/payroll_entry.js
+++ b/erpnext/payroll/doctype/payroll_entry/payroll_entry.js
@@ -151,6 +151,10 @@
 		filters['company'] = frm.doc.company;
 		filters['start_date'] = frm.doc.start_date;
 		filters['end_date'] = frm.doc.end_date;
+		filters['salary_slip_based_on_timesheet'] = frm.doc.salary_slip_based_on_timesheet;
+		filters['payroll_frequency'] = frm.doc.payroll_frequency;
+		filters['payroll_payable_account'] = frm.doc.payroll_payable_account;
+		filters['currency'] = frm.doc.currency;
 
 		if (frm.doc.department) {
 			filters['department'] = frm.doc.department;
diff --git a/erpnext/payroll/doctype/payroll_entry/payroll_entry.py b/erpnext/payroll/doctype/payroll_entry/payroll_entry.py
index 4c9469e..3953b46 100644
--- a/erpnext/payroll/doctype/payroll_entry/payroll_entry.py
+++ b/erpnext/payroll/doctype/payroll_entry/payroll_entry.py
@@ -52,49 +52,32 @@
 			Returns list of active employees based on selected criteria
 			and for which salary structure exists
 		"""
-		cond = self.get_filter_condition()
-		cond += self.get_joining_relieving_condition()
+		self.check_mandatory()
+		filters = self.make_filters()
+		cond = get_filter_condition(filters)
+		cond += get_joining_relieving_condition(self.start_date, self.end_date)
 
 		condition = ''
 		if self.payroll_frequency:
 			condition = """and payroll_frequency = '%(payroll_frequency)s'"""% {"payroll_frequency": self.payroll_frequency}
 
-		sal_struct = frappe.db.sql_list("""
-			select
-				name from `tabSalary Structure`
-			where
-				docstatus = 1 and
-				is_active = 'Yes'
-				and company = %(company)s
-				and currency = %(currency)s and
-				ifnull(salary_slip_based_on_timesheet,0) = %(salary_slip_based_on_timesheet)s
-				{condition}""".format(condition=condition),
-			{"company": self.company, "currency": self.currency, "salary_slip_based_on_timesheet":self.salary_slip_based_on_timesheet})
-
+		sal_struct = get_sal_struct(self.company, self.currency, self.salary_slip_based_on_timesheet, condition)
 		if sal_struct:
 			cond += "and t2.salary_structure IN %(sal_struct)s "
 			cond += "and t2.payroll_payable_account = %(payroll_payable_account)s "
 			cond += "and %(from_date)s >= t2.from_date"
-			emp_list = frappe.db.sql("""
-				select
-					distinct t1.name as employee, t1.employee_name, t1.department, t1.designation
-				from
-					`tabEmployee` t1, `tabSalary Structure Assignment` t2
-				where
-					t1.name = t2.employee
-					and t2.docstatus = 1
-			%s order by t2.from_date desc
-			""" % cond, {"sal_struct": tuple(sal_struct), "from_date": self.end_date, "payroll_payable_account": self.payroll_payable_account}, as_dict=True)
-
-			emp_list = self.remove_payrolled_employees(emp_list)
+			emp_list = get_emp_list(sal_struct, cond, self.end_date, self.payroll_payable_account)
+			emp_list = remove_payrolled_employees(emp_list, self.start_date, self.end_date)
 			return emp_list
 
-	def remove_payrolled_employees(self, emp_list):
-		for employee_details in emp_list:
-			if frappe.db.exists("Salary Slip", {"employee": employee_details.employee, "start_date": self.start_date, "end_date": self.end_date, "docstatus": 1}):
-				emp_list.remove(employee_details)
+	def make_filters(self):
+		filters = frappe._dict()
+		filters['company'] = self.company
+		filters['branch'] = self.branch
+		filters['department'] = self.department
+		filters['designation'] = self.designation
 
-		return emp_list
+		return filters
 
 	@frappe.whitelist()
 	def fill_employee_details(self):
@@ -122,23 +105,6 @@
 		if self.validate_attendance:
 			return self.validate_employee_attendance()
 
-	def get_filter_condition(self):
-		self.check_mandatory()
-
-		cond = ''
-		for f in ['company', 'branch', 'department', 'designation']:
-			if self.get(f):
-				cond += " and t1." + f + " = " + frappe.db.escape(self.get(f))
-
-		return cond
-
-	def get_joining_relieving_condition(self):
-		cond = """
-			and ifnull(t1.date_of_joining, '0000-00-00') <= '%(end_date)s'
-			and ifnull(t1.relieving_date, '2199-12-31') >= '%(start_date)s'
-		""" % {"start_date": self.start_date, "end_date": self.end_date}
-		return cond
-
 	def check_mandatory(self):
 		for fieldname in ['company', 'start_date', 'end_date']:
 			if not self.get(fieldname):
@@ -451,6 +417,53 @@
 			marked_days = attendances[0][0]
 		return marked_days
 
+def get_sal_struct(company, currency, salary_slip_based_on_timesheet, condition):
+	return frappe.db.sql_list("""
+		select
+			name from `tabSalary Structure`
+		where
+			docstatus = 1 and
+			is_active = 'Yes'
+			and company = %(company)s
+			and currency = %(currency)s and
+			ifnull(salary_slip_based_on_timesheet,0) = %(salary_slip_based_on_timesheet)s
+			{condition}""".format(condition=condition),
+		{"company": company, "currency": currency, "salary_slip_based_on_timesheet": salary_slip_based_on_timesheet})
+
+def get_filter_condition(filters):
+	cond = ''
+	for f in ['company', 'branch', 'department', 'designation']:
+		if filters.get(f):
+			cond += " and t1." + f + " = " + frappe.db.escape(filters.get(f))
+
+	return cond
+
+def get_joining_relieving_condition(start_date, end_date):
+	cond = """
+		and ifnull(t1.date_of_joining, '0000-00-00') <= '%(end_date)s'
+		and ifnull(t1.relieving_date, '2199-12-31') >= '%(start_date)s'
+	""" % {"start_date": start_date, "end_date": end_date}
+	return cond
+
+def get_emp_list(sal_struct, cond, end_date, payroll_payable_account):
+	return frappe.db.sql("""
+			select
+				distinct t1.name as employee, t1.employee_name, t1.department, t1.designation
+			from
+				`tabEmployee` t1, `tabSalary Structure Assignment` t2
+			where
+				t1.name = t2.employee
+				and t2.docstatus = 1
+		%s order by t2.from_date desc
+		""" % cond, {"sal_struct": tuple(sal_struct), "from_date": end_date, "payroll_payable_account": payroll_payable_account}, as_dict=True)
+
+def remove_payrolled_employees(emp_list, start_date, end_date):
+	for employee_details in emp_list:
+		if frappe.db.exists("Salary Slip", {"employee": employee_details.employee, "start_date": start_date, "end_date": end_date, "docstatus": 1}):
+			emp_list.remove(employee_details)
+
+	return emp_list
+
 @frappe.whitelist()
 def get_start_end_dates(payroll_frequency, start_date=None, company=None):
 	'''Returns dict of start and end dates for given payroll frequency based on start_date'''
@@ -639,39 +652,41 @@
 			'start': start, 'page_len': page_len
 		})
 
-def get_employee_with_existing_salary_slip(start_date, end_date, company):
-	return frappe.db.sql_list("""
-		select employee from `tabSalary Slip`
-		where
-			(start_date between %(start_date)s and %(end_date)s
-		or
-			end_date between %(start_date)s and %(end_date)s
-		or
-			%(start_date)s between start_date and end_date)
-		and company = %(company)s
-		and docstatus = 1
-	""", {'start_date': start_date, 'end_date': end_date, 'company': company})
+def get_employee_list(filters):
+	cond = get_filter_condition(filters)
+	cond += get_joining_relieving_condition(filters.start_date, filters.end_date)
+	condition = """and payroll_frequency = '%(payroll_frequency)s'"""% {"payroll_frequency": filters.payroll_frequency}
+	sal_struct = get_sal_struct(filters.company, filters.currency, filters.salary_slip_based_on_timesheet, condition)
+	if sal_struct:
+		cond += "and t2.salary_structure IN %(sal_struct)s "
+		cond += "and t2.payroll_payable_account = %(payroll_payable_account)s "
+		cond += "and %(from_date)s >= t2.from_date"
+		emp_list = get_emp_list(sal_struct, cond, filters.end_date, filters.payroll_payable_account)
+		emp_list = remove_payrolled_employees(emp_list, filters.start_date, filters.end_date)
+		return emp_list
 
 @frappe.whitelist()
 @frappe.validate_and_sanitize_search_inputs
 def employee_query(doctype, txt, searchfield, start, page_len, filters):
 	filters = frappe._dict(filters)
 	conditions = []
-	exclude_employees = []
+	include_employees = []
 	emp_cond = ''
 	if filters.start_date and filters.end_date:
-		employee_list = get_employee_with_existing_salary_slip(filters.start_date, filters.end_date, filters.company)
+		employee_list = get_employee_list(filters)
 		emp = filters.get('employees')
+		include_employees = [employee.employee for employee in employee_list if employee.employee not in emp]
 		filters.pop('start_date')
 		filters.pop('end_date')
+		filters.pop('salary_slip_based_on_timesheet')
+		filters.pop('payroll_frequency')
+		filters.pop('payroll_payable_account')
+		filters.pop('currency')
 		if filters.employees is not None:
 			filters.pop('employees')
-		if employee_list:
-			exclude_employees.extend(employee_list)
-		if emp:
-			exclude_employees.extend(emp)
-		if exclude_employees:
-			emp_cond += 'and employee not in %(exclude_employees)s'
+
+		if include_employees:
+			emp_cond += 'and employee in %(include_employees)s'
 
 	return frappe.db.sql("""select name, employee_name from `tabEmployee`
 		where status = 'Active'
@@ -695,4 +710,4 @@
 			'_txt': txt.replace("%", ""),
 			'start': start,
 			'page_len': page_len,
-			'exclude_employees': exclude_employees})
+			'include_employees': include_employees})
diff --git a/erpnext/payroll/doctype/salary_structure/salary_structure.js b/erpnext/payroll/doctype/salary_structure/salary_structure.js
index b539b1b..e00bd87 100755
--- a/erpnext/payroll/doctype/salary_structure/salary_structure.js
+++ b/erpnext/payroll/doctype/salary_structure/salary_structure.js
@@ -133,8 +133,6 @@
 			title: __("Assign to Employees"),
 			fields: [
 				{fieldname: "sec_break", fieldtype: "Section Break", label: __("Filter Employees By (Optional)")},
-				{fieldname: "company", fieldtype: "Link", options: "Company", label: __("Company"), default: frm.doc.company, read_only:1},
-				{fieldname: "currency", fieldtype: "Link", options: "Currency", label: __("Currency"), default: frm.doc.currency, read_only:1},
 				{fieldname: "grade", fieldtype: "Link", options: "Employee Grade", label: __("Employee Grade")},
 				{fieldname:'department', fieldtype:'Link', options: 'Department', label: __('Department')},
 				{fieldname:'designation', fieldtype:'Link', options: 'Designation', label: __('Designation')},
diff --git a/erpnext/payroll/doctype/salary_structure/salary_structure.py b/erpnext/payroll/doctype/salary_structure/salary_structure.py
index 352c180..58c445f 100644
--- a/erpnext/payroll/doctype/salary_structure/salary_structure.py
+++ b/erpnext/payroll/doctype/salary_structure/salary_structure.py
@@ -88,7 +88,7 @@
 		return employees
 
 	@frappe.whitelist()
-	def assign_salary_structure(self, grade=None, department=None, designation=None,employee=None,
+	def assign_salary_structure(self, grade=None, department=None, designation=None, employee=None,
 			payroll_payable_account=None, from_date=None, base=None, variable=None, income_tax_slab=None):
 		employees = self.get_employees(company= self.company, grade= grade,department= department,designation= designation,name=employee)
 
diff --git a/erpnext/projects/doctype/task/task.json b/erpnext/projects/doctype/task/task.json
index 160cc58..ef4740d 100644
--- a/erpnext/projects/doctype/task/task.json
+++ b/erpnext/projects/doctype/task/task.json
@@ -11,15 +11,16 @@
   "project",
   "issue",
   "type",
+  "color",
   "is_group",
   "is_template",
   "column_break0",
   "status",
   "priority",
   "task_weight",
-  "completed_by",
-  "color",
   "parent_task",
+  "completed_by",
+  "completed_on",
   "sb_timeline",
   "exp_start_date",
   "expected_time",
@@ -358,6 +359,7 @@
    "read_only": 1
   },
   {
+   "depends_on": "eval: doc.status == \"Completed\"",
    "fieldname": "completed_by",
    "fieldtype": "Link",
    "label": "Completed By",
@@ -381,6 +383,13 @@
    "fieldname": "duration",
    "fieldtype": "Int",
    "label": "Duration (Days)"
+  },
+  {
+   "depends_on": "eval: doc.status == \"Completed\"",
+   "fieldname": "completed_on",
+   "fieldtype": "Date",
+   "label": "Completed On",
+   "mandatory_depends_on": "eval: doc.status == \"Completed\""
   }
  ],
  "icon": "fa fa-check",
@@ -388,7 +397,7 @@
  "is_tree": 1,
  "links": [],
  "max_attachments": 5,
- "modified": "2020-12-28 11:32:58.714991",
+ "modified": "2021-04-16 12:46:51.556741",
  "modified_by": "Administrator",
  "module": "Projects",
  "name": "Task",
diff --git a/erpnext/projects/doctype/task/task.py b/erpnext/projects/doctype/task/task.py
index 855ff5f..d1583f1 100755
--- a/erpnext/projects/doctype/task/task.py
+++ b/erpnext/projects/doctype/task/task.py
@@ -36,6 +36,7 @@
 		self.validate_status()
 		self.update_depends_on()
 		self.validate_dependencies_for_template_task()
+		self.validate_completed_on()
 
 	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):
@@ -100,6 +101,10 @@
 					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_completed_on(self):
+		if self.completed_on and getdate(self.completed_on) > getdate():
+			frappe.throw(_("Completed On cannot be greater than Today"))
+
 	def update_depends_on(self):
 		depends_on_tasks = self.depends_on_tasks or ""
 		for d in self.depends_on:
diff --git a/erpnext/projects/report/delayed_tasks_summary/__init__.py b/erpnext/projects/report/delayed_tasks_summary/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/projects/report/delayed_tasks_summary/__init__.py
diff --git a/erpnext/projects/report/delayed_tasks_summary/delayed_tasks_summary.js b/erpnext/projects/report/delayed_tasks_summary/delayed_tasks_summary.js
new file mode 100644
index 0000000..5aa44c0
--- /dev/null
+++ b/erpnext/projects/report/delayed_tasks_summary/delayed_tasks_summary.js
@@ -0,0 +1,41 @@
+// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+/* eslint-disable */
+
+frappe.query_reports["Delayed Tasks Summary"] = {
+	"filters": [
+		{
+			"fieldname": "from_date",
+			"label": __("From Date"),
+			"fieldtype": "Date"
+		},
+		{
+			"fieldname": "to_date",
+			"label": __("To Date"),
+			"fieldtype": "Date"
+		},
+		{
+			"fieldname": "priority",
+			"label": __("Priority"),
+			"fieldtype": "Select",
+			"options": ["", "Low", "Medium", "High", "Urgent"]
+		},
+		{
+			"fieldname": "status",
+			"label": __("Status"),
+			"fieldtype": "Select",
+			"options": ["", "Open", "Working","Pending Review","Overdue","Completed"]
+		},
+	],
+	"formatter": function(value, row, column, data, default_formatter) {
+		value = default_formatter(value, row, column, data);
+		if (column.id == "delay") {
+			if (data["delay"] > 0) {
+				value = `<p style="color: red; font-weight: bold">${value}</p>`;
+			} else {
+				value = `<p style="color: green; font-weight: bold">${value}</p>`;
+			}
+		}
+		return value
+	}
+};
diff --git a/erpnext/projects/report/delayed_tasks_summary/delayed_tasks_summary.json b/erpnext/projects/report/delayed_tasks_summary/delayed_tasks_summary.json
new file mode 100644
index 0000000..100c422
--- /dev/null
+++ b/erpnext/projects/report/delayed_tasks_summary/delayed_tasks_summary.json
@@ -0,0 +1,29 @@
+{
+ "add_total_row": 0,
+ "columns": [],
+ "creation": "2021-03-25 15:03:19.857418",
+ "disable_prepared_report": 0,
+ "disabled": 0,
+ "docstatus": 0,
+ "doctype": "Report",
+ "filters": [],
+ "idx": 0,
+ "is_standard": "Yes",
+ "modified": "2021-04-15 15:49:35.432486",
+ "modified_by": "Administrator",
+ "module": "Projects",
+ "name": "Delayed Tasks Summary",
+ "owner": "Administrator",
+ "prepared_report": 0,
+ "ref_doctype": "Task",
+ "report_name": "Delayed Tasks Summary",
+ "report_type": "Script Report",
+ "roles": [
+  {
+   "role": "Projects User"
+  },
+  {
+   "role": "Projects Manager"
+  }
+ ]
+}
\ No newline at end of file
diff --git a/erpnext/projects/report/delayed_tasks_summary/delayed_tasks_summary.py b/erpnext/projects/report/delayed_tasks_summary/delayed_tasks_summary.py
new file mode 100644
index 0000000..cdabe64
--- /dev/null
+++ b/erpnext/projects/report/delayed_tasks_summary/delayed_tasks_summary.py
@@ -0,0 +1,133 @@
+# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe.utils import date_diff, nowdate
+
+def execute(filters=None):
+	columns, data = [], []
+	data = get_data(filters)
+	columns = get_columns()
+	charts = get_chart_data(data)
+	return columns, data, None, charts
+
+def get_data(filters):
+	conditions = get_conditions(filters)
+	tasks = frappe.get_all("Task",
+			filters = conditions,
+			fields = ["name", "subject", "exp_start_date", "exp_end_date",
+					"status", "priority", "completed_on", "progress"],
+			order_by="creation"
+		)
+	for task in tasks:
+		if task.exp_end_date:
+			if task.completed_on:
+				task.delay = date_diff(task.completed_on, task.exp_end_date)
+			elif task.status == "Completed":
+				# task is completed but completed on is not set (for older tasks)
+				task.delay = 0
+			else:
+				# task not completed
+				task.delay = date_diff(nowdate(), task.exp_end_date)
+		else:
+			# task has no end date, hence no delay
+			task.delay = 0
+
+	# Sort by descending order of delay
+	tasks.sort(key=lambda x: x["delay"], reverse=True)
+	return tasks
+
+def get_conditions(filters):
+	conditions = frappe._dict()
+	keys = ["priority", "status"]
+	for key in keys:
+		if filters.get(key):
+			conditions[key] = filters.get(key)
+	if filters.get("from_date"):
+		conditions.exp_end_date = [">=", filters.get("from_date")]
+	if filters.get("to_date"):
+		conditions.exp_start_date = ["<=", filters.get("to_date")]
+	return conditions
+
+def get_chart_data(data):
+	delay, on_track = 0, 0
+	for entry in data:
+		if entry.get("delay") > 0:
+			delay = delay + 1
+		else:
+			on_track = on_track + 1
+	charts = {
+		"data": {
+			"labels": ["On Track", "Delayed"],
+			"datasets": [
+				{
+					"name": "Delayed",
+					"values": [on_track, delay]
+				}
+			]
+		},
+		"type": "percentage",
+		"colors": ["#84D5BA", "#CB4B5F"]
+	}
+	return charts
+
+def get_columns():
+	columns = [
+		{
+			"fieldname": "name",
+			"fieldtype": "Link",
+			"label": "Task",
+			"options": "Task",
+			"width": 150
+		},
+		{
+			"fieldname": "subject",
+			"fieldtype": "Data",
+			"label": "Subject",
+			"width": 200
+		},
+		{
+			"fieldname": "status",
+			"fieldtype": "Data",
+			"label": "Status",
+			"width": 100
+		},
+		{
+			"fieldname": "priority",
+			"fieldtype": "Data",
+			"label": "Priority",
+			"width": 80
+		},
+		{
+			"fieldname": "progress",
+			"fieldtype": "Data",
+			"label": "Progress (%)",
+			"width": 120
+		},
+		{
+			"fieldname": "exp_start_date",
+			"fieldtype": "Date",
+			"label": "Expected Start Date",
+			"width": 150
+		},
+		{
+			"fieldname": "exp_end_date",
+			"fieldtype": "Date",
+			"label": "Expected End Date",
+			"width": 150
+		},
+		{
+			"fieldname": "completed_on",
+			"fieldtype": "Date",
+			"label": "Actual End Date",
+			"width": 130
+		},
+		{
+			"fieldname": "delay",
+			"fieldtype": "Data",
+			"label": "Delay (In Days)",
+			"width": 120
+		}
+	]
+	return columns
diff --git a/erpnext/projects/report/delayed_tasks_summary/test_delayed_tasks_summary.py b/erpnext/projects/report/delayed_tasks_summary/test_delayed_tasks_summary.py
new file mode 100644
index 0000000..dbeedb4
--- /dev/null
+++ b/erpnext/projects/report/delayed_tasks_summary/test_delayed_tasks_summary.py
@@ -0,0 +1,54 @@
+from __future__ import unicode_literals
+import unittest
+import frappe
+from frappe.utils import nowdate, add_days, add_months
+from erpnext.projects.doctype.task.test_task import create_task
+from erpnext.projects.report.delayed_tasks_summary.delayed_tasks_summary import execute
+
+class TestDelayedTasksSummary(unittest.TestCase):
+	@classmethod
+	def setUp(self):
+		task1 = create_task("_Test Task 98", add_days(nowdate(), -10), nowdate())
+		create_task("_Test Task 99", add_days(nowdate(), -10), add_days(nowdate(), -1))
+		
+		task1.status = "Completed"
+		task1.completed_on = add_days(nowdate(), -1)
+		task1.save()
+
+	def test_delayed_tasks_summary(self):
+		filters = frappe._dict({
+			"from_date": add_months(nowdate(), -1),
+			"to_date": nowdate(),
+			"priority": "Low",
+			"status": "Open"
+		})
+		expected_data = [
+			{
+				"subject": "_Test Task 99",
+				"status": "Open",
+				"priority": "Low",
+				"delay": 1
+			},
+			{
+				"subject": "_Test Task 98",
+				"status": "Completed",
+				"priority": "Low",
+				"delay": -1
+			}
+		]
+		report = execute(filters)
+		data = list(filter(lambda x: x.subject == "_Test Task 99", report[1]))[0]
+		
+		for key in ["subject", "status", "priority", "delay"]:
+			self.assertEqual(expected_data[0].get(key), data.get(key))
+
+		filters.status = "Completed"
+		report = execute(filters)
+		data = list(filter(lambda x: x.subject == "_Test Task 98", report[1]))[0]
+
+		for key in ["subject", "status", "priority", "delay"]:
+			self.assertEqual(expected_data[1].get(key), data.get(key))
+
+	def tearDown(self):
+		for task in ["_Test Task 98", "_Test Task 99"]:
+			frappe.get_doc("Task", {"subject": task}).delete()
\ No newline at end of file
diff --git a/erpnext/projects/workspace/projects/projects.json b/erpnext/projects/workspace/projects/projects.json
index dbbd7e1..0ec1702 100644
--- a/erpnext/projects/workspace/projects/projects.json
+++ b/erpnext/projects/workspace/projects/projects.json
@@ -15,6 +15,7 @@
  "hide_custom": 0,
  "icon": "project",
  "idx": 0,
+ "is_default": 0,
  "is_standard": 1,
  "label": "Projects",
  "links": [
@@ -148,9 +149,19 @@
    "link_type": "Report",
    "onboard": 0,
    "type": "Link"
+  },
+  {
+   "dependencies": "Task",
+   "hidden": 0,
+   "is_query_report": 1,
+   "label": "Delayed Tasks Summary",
+   "link_to": "Delayed Tasks Summary",
+   "link_type": "Report",
+   "onboard": 0,
+   "type": "Link"
   }
  ],
- "modified": "2020-12-01 13:38:37.856224",
+ "modified": "2021-03-26 16:32:00.628561",
  "modified_by": "Administrator",
  "module": "Projects",
  "name": "Projects",
diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js
index 6c2144d..a0398e7 100644
--- a/erpnext/public/js/controllers/transaction.js
+++ b/erpnext/public/js/controllers/transaction.js
@@ -1103,6 +1103,8 @@
 				to_currency: to_currency,
 				args: args
 			},
+			freeze: true,
+			freeze_message: __("Fetching exchange rates ..."),
 			callback: function(r) {
 				callback(flt(r.message));
 			}
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 e0d5b73..9fb3943 100644
--- a/erpnext/selling/page/point_of_sale/pos_item_selector.js
+++ b/erpnext/selling/page/point_of_sale/pos_item_selector.js
@@ -159,6 +159,31 @@
 	bind_events() {
 		const me = this;
 		window.onScan = onScan;
+
+		onScan.decodeKeyEvent = function (oEvent) {
+			var iCode = this._getNormalizedKeyNum(oEvent);
+			switch (true) {
+				case iCode >= 48 && iCode <= 90: // numbers and letters
+				case iCode >= 106 && iCode <= 111: // operations on numeric keypad (+, -, etc.)
+				case (iCode >= 160 && iCode <= 164) || iCode == 170: // ^ ! # $ *
+				case iCode >= 186 && iCode <= 194: // (; = , - . / `)
+				case iCode >= 219 && iCode <= 222: // ([ \ ] ')
+					if (oEvent.key !== undefined && oEvent.key !== '') {
+						return oEvent.key;
+					}
+
+					var sDecoded = String.fromCharCode(iCode);
+					switch (oEvent.shiftKey) {
+						case false: sDecoded = sDecoded.toLowerCase(); break;
+						case true: sDecoded = sDecoded.toUpperCase(); break;
+					}
+					return sDecoded;
+				case iCode >= 96 && iCode <= 105: // numbers on numeric keypad
+					return 0 + (iCode - 96);
+			}
+			return '';
+		};
+
 		onScan.attachTo(document, {
 			onScan: (sScancode) => {
 				if (this.search_field && this.$component.is(':visible')) {
diff --git a/erpnext/setup/workspace/home/home.json b/erpnext/setup/workspace/home/home.json
index 305456b..1576d5a 100644
--- a/erpnext/setup/workspace/home/home.json
+++ b/erpnext/setup/workspace/home/home.json
@@ -248,177 +248,9 @@
    "link_type": "DocType",
    "onboard": 1,
    "type": "Link"
-  },
-  {
-   "hidden": 0,
-   "is_query_report": 0,
-   "label": "Healthcare",
-   "onboard": 0,
-   "type": "Card Break"
-  },
-  {
-   "dependencies": "",
-   "hidden": 0,
-   "is_query_report": 0,
-   "label": "Patient",
-   "link_to": "Patient",
-   "link_type": "DocType",
-   "onboard": 1,
-   "type": "Link"
-  },
-  {
-   "dependencies": "",
-   "hidden": 0,
-   "is_query_report": 0,
-   "label": "Diagnosis",
-   "link_to": "Diagnosis",
-   "link_type": "DocType",
-   "onboard": 1,
-   "type": "Link"
-  },
-  {
-   "hidden": 0,
-   "is_query_report": 0,
-   "label": "Education",
-   "onboard": 0,
-   "type": "Card Break"
-  },
-  {
-   "dependencies": "",
-   "hidden": 0,
-   "is_query_report": 0,
-   "label": "Student",
-   "link_to": "Student",
-   "link_type": "DocType",
-   "onboard": 1,
-   "type": "Link"
-  },
-  {
-   "dependencies": "",
-   "hidden": 0,
-   "is_query_report": 0,
-   "label": "Instructor",
-   "link_to": "Instructor",
-   "link_type": "DocType",
-   "onboard": 1,
-   "type": "Link"
-  },
-  {
-   "dependencies": "",
-   "hidden": 0,
-   "is_query_report": 0,
-   "label": "Course",
-   "link_to": "Course",
-   "link_type": "DocType",
-   "onboard": 1,
-   "type": "Link"
-  },
-  {
-   "dependencies": "",
-   "hidden": 0,
-   "is_query_report": 0,
-   "label": "Room",
-   "link_to": "Room",
-   "link_type": "DocType",
-   "onboard": 1,
-   "type": "Link"
-  },
-  {
-   "hidden": 0,
-   "is_query_report": 0,
-   "label": "Non Profit",
-   "onboard": 0,
-   "type": "Card Break"
-  },
-  {
-   "dependencies": "",
-   "hidden": 0,
-   "is_query_report": 0,
-   "label": "Donor",
-   "link_to": "Donor",
-   "link_type": "DocType",
-   "onboard": 1,
-   "type": "Link"
-  },
-  {
-   "dependencies": "",
-   "hidden": 0,
-   "is_query_report": 0,
-   "label": "Member",
-   "link_to": "Member",
-   "link_type": "DocType",
-   "onboard": 1,
-   "type": "Link"
-  },
-  {
-   "dependencies": "",
-   "hidden": 0,
-   "is_query_report": 0,
-   "label": "Volunteer",
-   "link_to": "Volunteer",
-   "link_type": "DocType",
-   "onboard": 1,
-   "type": "Link"
-  },
-  {
-   "dependencies": "",
-   "hidden": 0,
-   "is_query_report": 0,
-   "label": "Chapter",
-   "link_to": "Chapter",
-   "link_type": "DocType",
-   "onboard": 1,
-   "type": "Link"
-  },
-  {
-   "hidden": 0,
-   "is_query_report": 0,
-   "label": "Agriculture",
-   "onboard": 0,
-   "type": "Card Break"
-  },
-  {
-   "dependencies": "",
-   "hidden": 0,
-   "is_query_report": 0,
-   "label": "Location",
-   "link_to": "Location",
-   "link_type": "DocType",
-   "onboard": 1,
-   "type": "Link"
-  },
-  {
-   "dependencies": "",
-   "hidden": 0,
-   "is_query_report": 0,
-   "label": "Crop",
-   "link_to": "Crop",
-   "link_type": "DocType",
-   "onboard": 1,
-   "type": "Link"
-  },
-  {
-   "dependencies": "",
-   "hidden": 0,
-   "is_query_report": 0,
-   "label": "Crop Cycle",
-   "link_to": "Crop Cycle",
-   "link_type": "DocType",
-   "onboard": 1,
-   "type": "Link"
-  },
-  {
-   "dependencies": "",
-   "hidden": 0,
-   "is_query_report": 0,
-   "label": "Fertilizer",
-   "link_to": "Fertilizer",
-   "link_type": "DocType",
-   "onboard": 1,
-   "type": "Link"
   }
  ],
- "modified": "2021-03-16 15:59:58.416154",
+ "modified": "2021-04-19 15:48:44.089927",
  "modified_by": "Administrator",
  "module": "Setup",
  "name": "Home",
diff --git a/erpnext/stock/doctype/stock_settings/stock_settings.json b/erpnext/stock/doctype/stock_settings/stock_settings.json
index 84af57b..f18eabc 100644
--- a/erpnext/stock/doctype/stock_settings/stock_settings.json
+++ b/erpnext/stock/doctype/stock_settings/stock_settings.json
@@ -13,6 +13,7 @@
   "column_break_4",
   "valuation_method",
   "over_delivery_receipt_allowance",
+  "role_allowed_to_over_deliver_receive",
   "action_if_quality_inspection_is_not_submitted",
   "show_barcode_field",
   "clean_description_html",
@@ -234,6 +235,13 @@
    "fieldname": "disable_serial_no_and_batch_selector",
    "fieldtype": "Check",
    "label": "Disable Serial No And Batch Selector"
+  },
+  {
+   "description": "Users with this role are allowed to over deliver/receive against orders above the allowance percentage",
+   "fieldname": "role_allowed_to_over_deliver_receive",
+   "fieldtype": "Link",
+   "label": "Role Allowed to Over Deliver/Receive",
+   "options": "Role"
   }
  ],
  "icon": "icon-cog",
@@ -241,7 +249,7 @@
  "index_web_pages_for_search": 1,
  "issingle": 1,
  "links": [],
- "modified": "2021-01-18 13:15:38.352796",
+ "modified": "2021-03-11 18:48:14.513055",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Stock Settings",
diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py
index dedfe1d..1a61f30 100644
--- a/erpnext/stock/get_item_details.py
+++ b/erpnext/stock/get_item_details.py
@@ -609,8 +609,12 @@
 	meta = frappe.get_meta(args.parenttype or args.doctype)
 
 	if meta.get_field("currency") or args.get('currency'):
-		pl_details = get_price_list_currency_and_exchange_rate(args)
-		args.update(pl_details)
+		if not args.get("price_list_currency") or not args.get("plc_conversion_rate"):
+			# if currency and plc_conversion_rate exist then
+			# `get_price_list_currency_and_exchange_rate` has already been called
+			pl_details = get_price_list_currency_and_exchange_rate(args)
+			args.update(pl_details)
+
 		if meta.get_field("currency"):
 			validate_conversion_rate(args, meta)
 
@@ -1000,6 +1004,8 @@
 	args = process_args(args)
 
 	parent = get_price_list_currency_and_exchange_rate(args)
+	args.update(parent)
+
 	children = []
 
 	if "items" in args:
@@ -1064,7 +1070,7 @@
 	return frappe._dict({
 		"price_list_currency": price_list_currency,
 		"price_list_uom_dependant": price_list_uom_dependant,
-		"plc_conversion_rate": plc_conversion_rate
+		"plc_conversion_rate": plc_conversion_rate or 1
 	})
 
 @frappe.whitelist()
diff --git a/erpnext/stock/report/itemwise_recommended_reorder_level/itemwise_recommended_reorder_level.py b/erpnext/stock/report/itemwise_recommended_reorder_level/itemwise_recommended_reorder_level.py
index 5df3fa8..2f70523 100644
--- a/erpnext/stock/report/itemwise_recommended_reorder_level/itemwise_recommended_reorder_level.py
+++ b/erpnext/stock/report/itemwise_recommended_reorder_level/itemwise_recommended_reorder_level.py
@@ -55,19 +55,31 @@
 
 
 def get_consumed_items(condition):
+	purpose_to_exclude = [
+		"Material Transfer for Manufacture",
+		"Material Transfer",
+		"Send to Subcontractor"
+	]
+
+	condition += """
+		and (
+			purpose is NULL
+			or purpose not in ({})
+		)
+	""".format(', '.join([f"'{p}'" for p in purpose_to_exclude]))
+	condition = condition.replace("posting_date", "sle.posting_date")
+
 	consumed_items = frappe.db.sql("""
 		select item_code, abs(sum(actual_qty)) as consumed_qty
-		from `tabStock Ledger Entry`
-		where actual_qty < 0
+		from `tabStock Ledger Entry` as sle left join `tabStock Entry` as se
+			on sle.voucher_no = se.name
+		where
+			actual_qty < 0
 			and voucher_type not in ('Delivery Note', 'Sales Invoice')
 			%s
-		group by item_code
-	""" % condition, as_dict=1)
+		group by item_code""" % condition, as_dict=1)
 
-	consumed_items_map = {}
-	for item in consumed_items:
-		consumed_items_map.setdefault(item.item_code, item.consumed_qty)
-
+	consumed_items_map = {item.item_code : item.consumed_qty for item in consumed_items}
 	return consumed_items_map
 
 def get_delivered_items(condition):
diff --git a/requirements.txt b/requirements.txt
index 5a35236..377fd7d 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,15 +1,13 @@
-braintree==3.57.1
 frappe
-gocardless-pro==1.11.0
-googlemaps==3.1.1
-pandas>=1.0.5
-plaid-python>=7.0.0
-pycountry==19.8.18
-PyGithub==1.44.1
-python-stdnum==1.12
-python-youtube==0.6.0
-taxjar==1.9.0
-tweepy==3.8.0
-Unidecode==1.1.1
-WooCommerce==2.1.1
-pycryptodome==3.9.8
+gocardless-pro~=1.22.0
+googlemaps  # used in ERPNext, but dependency is defined in Frappe
+pandas~=1.1.5
+plaid-python~=7.2.1
+pycountry~=20.7.3
+PyGithub~=1.54.1
+python-stdnum~=1.16
+python-youtube~=0.8.0
+taxjar~=1.9.2
+tweepy~=3.10.0
+Unidecode~=1.2.0
+WooCommerce~=3.0.0