fix: resolving commits
diff --git a/erpnext/accounts/doctype/account/chart_of_accounts/verified/de_kontenplan_SKR03_gnucash.json b/erpnext/accounts/doctype/account/chart_of_accounts/verified/de_kontenplan_SKR03_gnucash.json
index 89465ee..ee501f6 100644
--- a/erpnext/accounts/doctype/account/chart_of_accounts/verified/de_kontenplan_SKR03_gnucash.json
+++ b/erpnext/accounts/doctype/account/chart_of_accounts/verified/de_kontenplan_SKR03_gnucash.json
@@ -63,17 +63,21 @@
 					"Gewinnermittlung \u00a74/3 nicht Ergebniswirksam": {
 						"account_number": "1371"
 					},
-					"Abziehbare VSt. 7%": {
-						"account_number": "1571"
-					},
-					"Abziehbare VSt. 19%": {
-						"account_number": "1576"
-					},
-					"Abziehbare VStr. nach \u00a713b UStG 19%": {
-						"account_number": "1577"
-					},
-					"Leistungen \u00a713b UStG 19% Vorsteuer, 19% Umsatzsteuer": {
-						"account_number": "3120"
+					"Abziehbare Vorsteuer": {
+						"account_type": "Tax",
+						"is_group": 1,
+						"Abziehbare Vorsteuer 7%": {
+							"account_number": "1571"
+						},
+						"Abziehbare Vorsteuer 19%": {
+							"account_number": "1576"
+						},
+						"Abziehbare Vorsteuer nach \u00a713b UStG 19%": {
+							"account_number": "1577"
+						},
+						"Leistungen \u00a713b UStG 19% Vorsteuer, 19% Umsatzsteuer": {
+							"account_number": "3120"
+						}
 					}
 				},
 				"III. Wertpapiere": {
@@ -196,6 +200,7 @@
 					},
 					"Umsatzsteuer": {
 						"is_group": 1,
+						"account_type": "Tax",
 						"Umsatzsteuer 7%": {
 							"account_number": "1771"
 						},
diff --git a/erpnext/accounts/doctype/account/chart_of_accounts/verified/de_kontenplan_SKR04.json b/erpnext/accounts/doctype/account/chart_of_accounts/verified/de_kontenplan_SKR04.json
index 7fa6708..57e8bdd 100644
--- a/erpnext/accounts/doctype/account/chart_of_accounts/verified/de_kontenplan_SKR04.json
+++ b/erpnext/accounts/doctype/account/chart_of_accounts/verified/de_kontenplan_SKR04.json
@@ -292,18 +292,21 @@
                         "Umsatzsteuerforderungen fr\u00fchere Jahre": {}
                     }, 
                     "Sonstige Verm\u00f6gensgegenst\u00e4nde oder sonstige Verbindlichkeiten": {
-                        "Abziehbare Vorsteuer": {}, 
-                        "Abziehbare Vorsteuer 16%": {}, 
-                        "Abziehbare Vorsteuer 19%": {}, 
-                        "Abziehbare Vorsteuer 7%": {}, 
-                        "Abziehbare Vorsteuer aus der Auslagerung von Gegenst\u00e4nden aus einem Unsatzsteuerlager": {}, 
-                        "Abziehbare Vorsteuer aus innergemeinschaftlichem Erwerb": {}, 
-                        "Abziehbare Vorsteuer aus innergemeinschaftlichem Erwerb 16%": {}, 
-                        "Abziehbare Vorsteuer aus innergemeinschaftlichem Erwerb 19%": {}, 
-                        "Abziehbare Vorsteuer aus innergemeinschaftlichem Erwerb von Neufahrzeugen von Lieferanten ohne Ust-Identifikationsnummer": {}, 
-                        "Abziehbare Vorsteuer nach \u00a7 13b UStG ": {}, 
-                        "Abziehbare Vorsteuer nach \u00a7 13b UStG 16%": {}, 
-                        "Abziehbare Vorsteuer nach \u00a7 13b UStG 19%": {}, 
+                        "Abziehbare Vorsteuer": {
+                            "account_type": "Tax",
+                            "is_group": 1,
+                            "Abziehbare Vorsteuer 16%": {},
+                            "Abziehbare Vorsteuer 19%": {},
+                            "Abziehbare Vorsteuer 7%": {},
+                            "Abziehbare Vorsteuer aus der Auslagerung von Gegenst\u00e4nden aus einem Unsatzsteuerlager": {},
+                            "Abziehbare Vorsteuer aus innergemeinschaftlichem Erwerb": {},
+                            "Abziehbare Vorsteuer aus innergemeinschaftlichem Erwerb 16%": {},
+                            "Abziehbare Vorsteuer aus innergemeinschaftlichem Erwerb 19%": {},
+                            "Abziehbare Vorsteuer aus innergemeinschaftlichem Erwerb von Neufahrzeugen von Lieferanten ohne Ust-Identifikationsnummer": {},
+                            "Abziehbare Vorsteuer nach \u00a7 13b UStG ": {},
+                            "Abziehbare Vorsteuer nach \u00a7 13b UStG 16%": {},
+                            "Abziehbare Vorsteuer nach \u00a7 13b UStG 19%": {}
+                        },
                         "Aufl\u00f6sung Vorsteuer aus Vorjahr \u00a7 4/3 EStG": {}, 
                         "Aufzuteilende Vorsteuer": {}, 
                         "Aufzuteilende Vorsteuer 16%": {}, 
@@ -673,23 +676,26 @@
                         "Sonstige Verrechnungskonten (Interimskonto)": {
                             "account_type": "Stock Received But Not Billed"
                         }, 
-                        "Umsatzsteuer": {}, 
-                        "Umsatzsteuer 16%": {}, 
-                        "Umsatzsteuer 19%": {}, 
-                        "Umsatzsteuer 7%": {}, 
-                        "Umsatzsteuer Vorjahr": {}, 
-                        "Umsatzsteuer aus der Auslagerung von Gegenst\u00e4nden aus einem Umsatzsteuerlager": {}, 
-                        "Umsatzsteuer aus im Inland steuerpflichtigen EG-Lieferungen": {}, 
-                        "Umsatzsteuer aus im Inland steuerpflichtigen EG-Lieferungen 19%": {}, 
-                        "Umsatzsteuer aus innergemeinschaftlichem Erwerb ": {}, 
-                        "Umsatzsteuer aus innergemeinschaftlichem Erwerb 16%": {}, 
-                        "Umsatzsteuer aus innergemeinschaftlichem Erwerb 19%": {}, 
-                        "Umsatzsteuer aus innergemeinschaftlichem Erwerb ohne Vorsteuerabzug": {}, 
-                        "Umsatzsteuer fr\u00fchere Jahre": {}, 
-                        "Umsatzsteuer laufendes Jahr": {}, 
-                        "Umsatzsteuer nach \u00a713b UStG": {}, 
-                        "Umsatzsteuer nach \u00a713b UStG 16%": {}, 
-                        "Umsatzsteuer nach \u00a713b UStG 19%": {}, 
+                        "Umsatzsteuer": {
+                            "account_type": "Tax",
+                            "is_group": 1,
+                            "Umsatzsteuer 16%": {},
+                            "Umsatzsteuer 19%": {},
+                            "Umsatzsteuer 7%": {},
+                            "Umsatzsteuer Vorjahr": {},
+                            "Umsatzsteuer aus der Auslagerung von Gegenst\u00e4nden aus einem Umsatzsteuerlager": {},
+                            "Umsatzsteuer aus im Inland steuerpflichtigen EG-Lieferungen": {},
+                            "Umsatzsteuer aus im Inland steuerpflichtigen EG-Lieferungen 19%": {},
+                            "Umsatzsteuer aus innergemeinschaftlichem Erwerb ": {},
+                            "Umsatzsteuer aus innergemeinschaftlichem Erwerb 16%": {},
+                            "Umsatzsteuer aus innergemeinschaftlichem Erwerb 19%": {},
+                            "Umsatzsteuer aus innergemeinschaftlichem Erwerb ohne Vorsteuerabzug": {},
+                            "Umsatzsteuer fr\u00fchere Jahre": {},
+                            "Umsatzsteuer laufendes Jahr": {},
+                            "Umsatzsteuer nach \u00a713b UStG": {},
+                            "Umsatzsteuer nach \u00a713b UStG 16%": {},
+                            "Umsatzsteuer nach \u00a713b UStG 19%": {}
+                        },
                         "Umsatzsteuer- Vorauszahlungen": {}, 
                         "Umsatzsteuer- Vorauszahlungen 1/11": {}, 
                         "Verbindlichkeiten aus Lohn- und Kirchensteuer": {}
diff --git a/erpnext/accounts/doctype/account/chart_of_accounts/verified/de_kontenplan_SKR04_with_account_number.json b/erpnext/accounts/doctype/account/chart_of_accounts/verified/de_kontenplan_SKR04_with_account_number.json
index 849df18..2bf55cf 100644
--- a/erpnext/accounts/doctype/account/chart_of_accounts/verified/de_kontenplan_SKR04_with_account_number.json
+++ b/erpnext/accounts/doctype/account/chart_of_accounts/verified/de_kontenplan_SKR04_with_account_number.json
@@ -659,6 +659,7 @@
                         },
                         "Abziehbare Vorsteuer (Gruppe)": {
                             "is_group": 1,
+                            "account_type": "Tax",
                             "Abziehbare Vorsteuer": {
                                 "account_number": "1400"
                             },
diff --git a/erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.js b/erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.js
index 297dd43..10f660a 100644
--- a/erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.js
+++ b/erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.js
@@ -8,6 +8,7 @@
 			return {
 				filters: {
 					company: ["in", frm.doc.company],
+					'is_company_account': 1
 				},
 			};
 		});
diff --git a/erpnext/accounts/doctype/item_tax_template/item_tax_template.json b/erpnext/accounts/doctype/item_tax_template/item_tax_template.json
index 8915f79..77c9e95 100644
--- a/erpnext/accounts/doctype/item_tax_template/item_tax_template.json
+++ b/erpnext/accounts/doctype/item_tax_template/item_tax_template.json
@@ -1,7 +1,7 @@
 {
+ "actions": [],
  "allow_import": 1,
  "allow_rename": 1,
- "autoname": "field:title",
  "creation": "2018-11-22 22:45:00.370913",
  "doctype": "DocType",
  "document_type": "Setup",
@@ -20,8 +20,7 @@
    "in_list_view": 1,
    "label": "Title",
    "no_copy": 1,
-   "reqd": 1,
-   "unique": 1
+   "reqd": 1
   },
   {
    "fieldname": "taxes",
@@ -33,12 +32,14 @@
   {
    "fieldname": "company",
    "fieldtype": "Link",
+   "in_list_view": 1,
    "label": "Company",
    "options": "Company",
    "reqd": 1
   }
  ],
- "modified": "2020-09-18 17:26:09.703215",
+ "links": [],
+ "modified": "2021-03-08 19:50:21.416513",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "Item Tax Template",
@@ -81,5 +82,6 @@
  "show_name_in_global_search": 1,
  "sort_field": "modified",
  "sort_order": "DESC",
+ "title_field": "title",
  "track_changes": 1
 }
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/item_tax_template/item_tax_template.py b/erpnext/accounts/doctype/item_tax_template/item_tax_template.py
index e77481d..d9155cb 100644
--- a/erpnext/accounts/doctype/item_tax_template/item_tax_template.py
+++ b/erpnext/accounts/doctype/item_tax_template/item_tax_template.py
@@ -11,6 +11,11 @@
 	def validate(self):
 		self.validate_tax_accounts()
 
+	def autoname(self):
+		if self.company and self.title:
+			abbr = frappe.get_cached_value('Company',  self.company,  'abbr')
+			self.name = '{0} - {1}'.format(self.title, abbr)
+
 	def validate_tax_accounts(self):
 		"""Check whether Tax Rate is not entered twice for same Tax Type"""
 		check_list = []
diff --git a/erpnext/accounts/doctype/mode_of_payment/mode_of_payment.py b/erpnext/accounts/doctype/mode_of_payment/mode_of_payment.py
index d54a47e..3247369 100644
--- a/erpnext/accounts/doctype/mode_of_payment/mode_of_payment.py
+++ b/erpnext/accounts/doctype/mode_of_payment/mode_of_payment.py
@@ -12,7 +12,7 @@
 		self.validate_accounts()
 		self.validate_repeating_companies()
 		self.validate_pos_mode_of_payment()
-	
+
 	def validate_repeating_companies(self):
 		"""Error when Same Company is entered multiple times in accounts"""
 		accounts_list = []
@@ -31,10 +31,10 @@
 
 	def validate_pos_mode_of_payment(self):
 		if not self.enabled:
-			pos_profiles = frappe.db.sql("""SELECT sip.parent FROM `tabSales Invoice Payment` sip 
+			pos_profiles = frappe.db.sql("""SELECT sip.parent FROM `tabSales Invoice Payment` sip
 				WHERE sip.parenttype = 'POS Profile' and sip.mode_of_payment = %s""", (self.name))
 			pos_profiles = list(map(lambda x: x[0], pos_profiles))
-			
+
 			if pos_profiles:
 				message = "POS Profile " + frappe.bold(", ".join(pos_profiles)) + " contains \
 					Mode of Payment " + frappe.bold(str(self.name)) + ". Please remove them to disable this mode."
diff --git a/erpnext/accounts/doctype/opening_invoice_creation_tool/opening_invoice_creation_tool.py b/erpnext/accounts/doctype/opening_invoice_creation_tool/opening_invoice_creation_tool.py
index 76027a3..e6449b7 100644
--- a/erpnext/accounts/doctype/opening_invoice_creation_tool/opening_invoice_creation_tool.py
+++ b/erpnext/accounts/doctype/opening_invoice_creation_tool/opening_invoice_creation_tool.py
@@ -198,6 +198,7 @@
 		try:
 			publish(idx, len(invoices), d.doctype)
 			doc = frappe.get_doc(d)
+			doc.flags.ignore_mandatory = True
 			doc.insert()
 			doc.submit()
 			frappe.db.commit()
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.js b/erpnext/accounts/doctype/payment_entry/payment_entry.js
index f5c488d..6412772 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.js
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.js
@@ -92,14 +92,16 @@
 		});
 
 		frm.set_query("reference_doctype", "references", function() {
-			if (frm.doc.party_type=="Customer") {
+			if (frm.doc.party_type == "Customer") {
 				var doctypes = ["Sales Order", "Sales Invoice", "Journal Entry", "Dunning"];
-			} else if (frm.doc.party_type=="Supplier") {
+			} else if (frm.doc.party_type == "Supplier") {
 				var doctypes = ["Purchase Order", "Purchase Invoice", "Journal Entry"];
-			} else if (frm.doc.party_type=="Employee") {
+			} else if (frm.doc.party_type == "Employee") {
 				var doctypes = ["Expense Claim", "Journal Entry"];
-			} else if (frm.doc.party_type=="Student") {
+			} else if (frm.doc.party_type == "Student") {
 				var doctypes = ["Fees"];
+			} else if (frm.doc.party_type == "Donor") {
+				var doctypes = ["Donation"];
 			} else {
 				var doctypes = ["Journal Entry"];
 			}
@@ -128,7 +130,7 @@
 			const child = locals[cdt][cdn];
 			const filters = {"docstatus": 1, "company": doc.company};
 			const party_type_doctypes = ['Sales Invoice', 'Sales Order', 'Purchase Invoice',
-				'Purchase Order', 'Expense Claim', 'Fees', 'Dunning'];
+				'Purchase Order', 'Expense Claim', 'Fees', 'Dunning', 'Donation'];
 
 			if (in_list(party_type_doctypes, child.reference_doctype)) {
 				filters[doc.party_type.toLowerCase()] = doc.party;
@@ -281,7 +283,7 @@
 		let party_types = Object.keys(frappe.boot.party_account_types);
 		if(frm.doc.party_type && !party_types.includes(frm.doc.party_type)){
 			frm.set_value("party_type", "");
-			frappe.throw(__("Party can only be one of "+ party_types.join(", ")));
+			frappe.throw(__("Party can only be one of {0}", [party_types.join(", ")]));
 		}
 
 		frm.set_query("party", function() {
@@ -705,7 +707,8 @@
 						(frm.doc.payment_type=="Receive" && frm.doc.party_type=="Customer") ||
 						(frm.doc.payment_type=="Pay" && frm.doc.party_type=="Supplier")  ||
 						(frm.doc.payment_type=="Pay" && frm.doc.party_type=="Employee") ||
-						(frm.doc.payment_type=="Receive" && frm.doc.party_type=="Student")
+						(frm.doc.payment_type=="Receive" && frm.doc.party_type=="Student") ||
+						(frm.doc.payment_type=="Receive" && frm.doc.party_type=="Donor")
 					) {
 						if(total_positive_outstanding > total_negative_outstanding)
 							if (!frm.doc.paid_amount)
@@ -748,7 +751,8 @@
 				(frm.doc.payment_type=="Receive" && frm.doc.party_type=="Customer") ||
 				(frm.doc.payment_type=="Pay" && frm.doc.party_type=="Supplier") ||
 				(frm.doc.payment_type=="Pay" && frm.doc.party_type=="Employee") ||
-				(frm.doc.payment_type=="Receive" && frm.doc.party_type=="Student")
+				(frm.doc.payment_type=="Receive" && frm.doc.party_type=="Student") ||
+				(frm.doc.payment_type=="Receive" && frm.doc.party_type=="Donor")
 			) {
 				if(total_positive_outstanding_including_order > paid_amount) {
 					var remaining_outstanding = total_positive_outstanding_including_order - paid_amount;
@@ -905,6 +909,12 @@
 				frappe.msgprint(__("Row #{0}: Reference Document Type must be one of Expense Claim or Journal Entry", [row.idx]));
 				return false;
 			}
+
+			if (frm.doc.party_type == "Donor" && row.reference_doctype != "Donation") {
+				frappe.model.set_value(row.doctype, row.name, "reference_doctype", null);
+				frappe.msgprint(__("Row #{0}: Reference Document Type must be Donation", [row.idx]));
+				return false;
+			}
 		}
 
 		if (row) {
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.json b/erpnext/accounts/doctype/payment_entry/payment_entry.json
index 2e1f201..328584a 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.json
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.json
@@ -536,7 +536,8 @@
    "fieldtype": "Data",
    "hidden": 1,
    "label": "Title",
-   "print_hide": 1
+   "print_hide": 1,
+   "read_only": 1
   },
   {
    "depends_on": "party",
@@ -588,7 +589,7 @@
  "index_web_pages_for_search": 1,
  "is_submittable": 1,
  "links": [],
- "modified": "2020-10-30 13:56:20.007336",
+ "modified": "2021-03-08 13:05:16.958866",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "Payment Entry",
@@ -632,4 +633,4 @@
  "sort_order": "DESC",
  "title_field": "title",
  "track_changes": 1
-}
\ No newline at end of file
+}
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py
index 31a4c8a..8acd92c 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.py
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py
@@ -72,6 +72,7 @@
 		self.update_outstanding_amounts()
 		self.update_advance_paid()
 		self.update_expense_claim()
+		self.update_donation()
 		self.update_payment_schedule()
 		self.set_status()
 
@@ -82,6 +83,7 @@
 		self.update_outstanding_amounts()
 		self.update_advance_paid()
 		self.update_expense_claim()
+		self.update_donation(cancel=1)
 		self.delink_advance_entry_references()
 		self.update_payment_schedule(cancel=1)
 		self.set_payment_req_status()
@@ -242,9 +244,11 @@
 		elif self.party_type == "Supplier":
 			valid_reference_doctypes = ("Purchase Order", "Purchase Invoice", "Journal Entry")
 		elif self.party_type == "Employee":
-			valid_reference_doctypes = ("Expense Claim", "Journal Entry", "Employee Advance")
+			valid_reference_doctypes = ("Expense Claim", "Journal Entry", "Employee Advance", "Gratuity")
 		elif self.party_type == "Shareholder":
 			valid_reference_doctypes = ("Journal Entry")
+		elif self.party_type == "Donor":
+			valid_reference_doctypes = ("Donation")
 
 		for d in self.get("references"):
 			if not d.allocated_amount:
@@ -455,6 +459,10 @@
 					.format(total_negative_outstanding), InvalidPaymentEntry)
 
 	def set_title(self):
+		if frappe.flags.in_import and self.title:
+			# do not set title dynamically if title exists during data import.
+			return
+
 		if self.payment_type in ("Receive", "Pay"):
 			self.title = self.party
 		else:
@@ -604,7 +612,7 @@
 		if self.payment_type in ("Receive", "Pay") and self.party:
 			for d in self.get("references"):
 				if d.allocated_amount \
-					and d.reference_doctype in ("Sales Order", "Purchase Order", "Employee Advance"):
+					and d.reference_doctype in ("Sales Order", "Purchase Order", "Employee Advance", "Gratuity"):
 						frappe.get_doc(d.reference_doctype, d.reference_name).set_total_advance_paid()
 
 	def update_expense_claim(self):
@@ -614,6 +622,13 @@
 					doc = frappe.get_doc("Expense Claim", d.reference_name)
 					update_reimbursed_amount(doc, self.name)
 
+	def update_donation(self, cancel=0):
+		if self.payment_type == "Receive" and self.party_type == "Donor" and self.party:
+			for d in self.get("references"):
+				if d.reference_doctype=="Donation" and d.reference_name:
+					is_paid = 0 if cancel else 1
+					frappe.db.set_value("Donation", d.reference_name, "paid", is_paid)
+
 	def on_recurring(self, reference_doc, auto_repeat_doc):
 		self.reference_no = reference_doc.name
 		self.reference_date = nowdate()
@@ -913,6 +928,9 @@
 		total_amount = ref_doc.get("grand_total")
 		exchange_rate = 1
 		outstanding_amount = ref_doc.get("outstanding_amount")
+	elif reference_doctype == "Donation":
+		total_amount = ref_doc.get("amount")
+		exchange_rate = 1
 	elif reference_doctype == "Dunning":
 		total_amount = ref_doc.get("dunning_amount")
 		exchange_rate = 1
@@ -932,6 +950,8 @@
 			exchange_rate = ref_doc.get("exchange_rate")
 			if party_account_currency != ref_doc.currency:
 				total_amount = flt(total_amount) * flt(exchange_rate)
+		elif ref_doc.doctype == "Gratuity":
+				total_amount = ref_doc.amount
 		if not total_amount:
 			if party_account_currency == company_currency:
 				total_amount = ref_doc.base_grand_total
@@ -955,6 +975,8 @@
 				outstanding_amount = flt(outstanding_amount) * flt(exchange_rate)
 				if party_account_currency == company_currency:
 					exchange_rate = 1
+		elif reference_doctype == "Gratuity":
+			outstanding_amount = ref_doc.amount - flt(ref_doc.paid_amount)
 		else:
 			outstanding_amount = flt(total_amount) - flt(ref_doc.advance_paid)
 	else:
@@ -996,7 +1018,7 @@
 			total_amount = flt(ref_doc.total_sanctioned_amount) + flt(ref_doc.total_taxes_and_charges)
 	elif ref_doc.doctype == "Employee Advance":
 		total_amount, exchange_rate = get_total_amount_exchange_rate_for_employee_advance(party_account_currency, ref_doc)
-		
+
 	if not total_amount:
 		total_amount, exchange_rate = get_total_amount_exchange_rate_base_on_currency(
 			party_account_currency, company_currency, ref_doc)
@@ -1160,10 +1182,12 @@
 		party_type = "Customer"
 	elif dt in ("Purchase Invoice", "Purchase Order"):
 		party_type = "Supplier"
-	elif dt in ("Expense Claim", "Employee Advance"):
+	elif dt in ("Expense Claim", "Employee Advance", "Gratuity"):
 		party_type = "Employee"
-	elif dt in ("Fees"):
+	elif dt == "Fees":
 		party_type = "Student"
+	elif dt == "Donation":
+		party_type = "Donor"
 	return party_type
 
 def set_party_account(dt, dn, doc, party_type):
@@ -1177,6 +1201,8 @@
 		party_account = doc.advance_account
 	elif dt == "Expense Claim":
 		party_account = doc.payable_account
+	elif dt == "Gratuity":
+		party_account = doc.payable_account
 	else:
 		party_account = get_party_account(party_type, doc.get(party_type.lower()), doc.company)
 	return party_account
@@ -1189,7 +1215,7 @@
 	return party_account_currency
 
 def set_payment_type(dt, doc):
-	if (dt == "Sales Order" or (dt in ("Sales Invoice", "Fees", "Dunning") and doc.outstanding_amount > 0)) \
+	if (dt in ("Sales Order", "Donation") or (dt in ("Sales Invoice", "Fees", "Dunning") and doc.outstanding_amount > 0)) \
 		or (dt=="Purchase Invoice" and doc.outstanding_amount < 0):
 			payment_type = "Receive"
 	else:
@@ -1222,6 +1248,12 @@
 	elif dt == "Dunning":
 		grand_total = doc.grand_total
 		outstanding_amount = doc.grand_total
+	elif dt == "Donation":
+		grand_total = doc.amount
+		outstanding_amount = doc.amount
+	elif dt == "Gratuity":
+		grand_total = doc.amount
+		outstanding_amount = flt(doc.amount) - flt(doc.paid_amount)
 	else:
 		if party_account_currency == doc.company_currency:
 			grand_total = flt(doc.get("base_rounded_total") or doc.base_grand_total)
@@ -1326,4 +1358,4 @@
 
 	}, target_doc, set_missing_values)
 
-	return doclist
\ No newline at end of file
+	return doclist
diff --git a/erpnext/accounts/doctype/pos_invoice/test_pos_invoice.py b/erpnext/accounts/doctype/pos_invoice/test_pos_invoice.py
index 15875af..eb52fd6 100644
--- a/erpnext/accounts/doctype/pos_invoice/test_pos_invoice.py
+++ b/erpnext/accounts/doctype/pos_invoice/test_pos_invoice.py
@@ -99,10 +99,10 @@
 		item_row = inv.get("items")[0]
 
 		add_items = [
-			(54, '_Test Account Excise Duty @ 12'),
-			(288, '_Test Account Excise Duty @ 15'),
-			(144, '_Test Account Excise Duty @ 20'),
-			(430, '_Test Item Tax Template 1')
+			(54, '_Test Account Excise Duty @ 12 - _TC'),
+			(288, '_Test Account Excise Duty @ 15 - _TC'),
+			(144, '_Test Account Excise Duty @ 20 - _TC'),
+			(430, '_Test Item Tax Template 1 - _TC')
 		]
 		for qty, item_tax_template in add_items:
 			item_row_copy = copy.deepcopy(item_row)
diff --git a/erpnext/accounts/doctype/pricing_rule/pricing_rule.json b/erpnext/accounts/doctype/pricing_rule/pricing_rule.json
index d08a854..3377164 100644
--- a/erpnext/accounts/doctype/pricing_rule/pricing_rule.json
+++ b/erpnext/accounts/doctype/pricing_rule/pricing_rule.json
@@ -357,7 +357,6 @@
    "reqd": 1
   },
   {
-   "depends_on": "eval: doc.selling == 1",
    "fieldname": "margin",
    "fieldtype": "Section Break",
    "label": "Margin"
@@ -565,7 +564,7 @@
  "icon": "fa fa-gift",
  "idx": 1,
  "links": [],
- "modified": "2020-12-04 00:36:24.698219",
+ "modified": "2021-03-01 23:18:38.717613",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "Pricing Rule",
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
index 451c936..18b6637 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
@@ -58,6 +58,7 @@
   "rejected_warehouse",
   "col_break_warehouse",
   "set_from_warehouse",
+  "supplier_warehouse",
   "is_subcontracted",
   "items_section",
   "update_stock",
@@ -1350,7 +1351,7 @@
    "options": "Company"
   },
   {
-   "depends_on": "eval:doc.update_stock && (doc.is_subcontracted==\"Yes\" || doc.is_internal_supplier)",
+   "depends_on": "eval:doc.update_stock && doc.is_internal_supplier",
    "description": "Sets 'From Warehouse' in each row of the items table.",
    "fieldname": "set_from_warehouse",
    "fieldtype": "Link",
@@ -1360,13 +1361,24 @@
    "print_hide": 1,
    "print_width": "50px",
    "width": "50px"
+  },
+  {
+   "depends_on": "eval:doc.update_stock && doc.is_subcontracted==\"Yes\"",
+   "fieldname": "supplier_warehouse",
+   "fieldtype": "Link",
+   "label": "Supplier Warehouse",
+   "no_copy": 1,
+   "options": "Warehouse",
+   "print_hide": 1,
+   "print_width": "50px",
+   "width": "50px"
   }
  ],
  "icon": "fa fa-file-text",
  "idx": 204,
  "is_submittable": 1,
  "links": [],
- "modified": "2020-12-26 20:49:03.305063",
+ "modified": "2021-03-09 21:12:30.422084",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "Purchase Invoice",
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
index dacd50a..5c4e32e 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
@@ -968,7 +968,7 @@
 		# base_rounding_adjustment may become zero due to small precision
 		# eg: rounding_adjustment = 0.01 and exchange rate = 0.05 and precision of base_rounding_adjustment is 2
 		#	then base_rounding_adjustment becomes zero and error is thrown in GL Entry
-		if self.rounding_adjustment and self.base_rounding_adjustment:
+		if not self.is_internal_transfer() and self.rounding_adjustment and self.base_rounding_adjustment:
 			round_off_account, round_off_cost_center = \
 				get_round_off_account_and_cost_center(self.company)
 
diff --git a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
index 2c088ce..ded293b 100644
--- a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
@@ -456,7 +456,7 @@
 		pi = make_purchase_invoice(company = "_Test Company with perpetual inventory", warehouse= "Stores - TCP1",
 			cost_center = "Main - TCP1", expense_account ="_Test Account Cost for Goods Sold - TCP1")
 
-		return_pi = make_purchase_invoice(is_return=1, return_against=pi.name, qty=-2, 
+		return_pi = make_purchase_invoice(is_return=1, return_against=pi.name, qty=-2,
 			company = "_Test Company with perpetual inventory", warehouse= "Stores - TCP1",
 			cost_center = "Main - TCP1", expense_account ="_Test Account Cost for Goods Sold - TCP1")
 
@@ -1031,7 +1031,7 @@
 	pi.is_return = args.is_return
 	pi.credit_to = args.return_against or "Creditors - _TC"
 	pi.is_subcontracted = args.is_subcontracted or "No"
-	if args.supplier_warehouse: 
+	if args.supplier_warehouse:
 		pi.supplier_warehouse = "_Test Warehouse 1 - _TC"
 
 	pi.append("items", {
diff --git a/erpnext/accounts/doctype/purchase_invoice/test_records.json b/erpnext/accounts/doctype/purchase_invoice/test_records.json
index 7030faf..e7166c5 100644
--- a/erpnext/accounts/doctype/purchase_invoice/test_records.json
+++ b/erpnext/accounts/doctype/purchase_invoice/test_records.json
@@ -18,7 +18,7 @@
     "expense_account": "_Test Account Cost for Goods Sold - _TC",
     "item_code": "_Test Item Home Desktop 100",
     "item_name": "_Test Item Home Desktop 100",
-    "item_tax_template": "_Test Account Excise Duty @ 10",
+    "item_tax_template": "_Test Account Excise Duty @ 10 - _TC",
     "parentfield": "items",
     "qty": 10,
     "rate": 50,
diff --git a/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json b/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json
index 07e75ac..96ad0fd 100644
--- a/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json
+++ b/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json
@@ -28,10 +28,16 @@
   "stock_qty",
   "sec_break1",
   "price_list_rate",
-  "discount_percentage",
-  "discount_amount",
   "col_break3",
   "base_price_list_rate",
+  "section_break_26",
+  "margin_type",
+  "margin_rate_or_amount",
+  "rate_with_margin",
+  "column_break_30",
+  "discount_percentage",
+  "discount_amount",
+  "base_rate_with_margin",
   "sec_break2",
   "rate",
   "amount",
@@ -789,6 +795,7 @@
    "fieldname": "stock_uom_rate",
    "fieldtype": "Currency",
    "label": "Rate of Stock UOM",
+   "no_copy": 1,
    "options": "currency",
    "read_only": 1
   },
@@ -799,12 +806,54 @@
    "no_copy": 1,
    "print_hide": 1,
    "read_only": 1
+  },
+  {
+   "collapsible": 1,
+   "fieldname": "section_break_26",
+   "fieldtype": "Section Break",
+   "label": "Discount and Margin"
+  },
+  {
+   "depends_on": "price_list_rate",
+   "fieldname": "margin_type",
+   "fieldtype": "Select",
+   "label": "Margin Type",
+   "options": "\nPercentage\nAmount",
+   "print_hide": 1
+  },
+  {
+   "depends_on": "eval:doc.margin_type && doc.price_list_rate",
+   "fieldname": "margin_rate_or_amount",
+   "fieldtype": "Float",
+   "label": "Margin Rate or Amount",
+   "print_hide": 1
+  },
+  {
+   "depends_on": "eval:doc.margin_type && doc.price_list_rate && doc.margin_rate_or_amount",
+   "fieldname": "rate_with_margin",
+   "fieldtype": "Currency",
+   "label": "Rate With Margin",
+   "options": "currency",
+   "read_only": 1
+  },
+  {
+   "fieldname": "column_break_30",
+   "fieldtype": "Column Break"
+  },
+  {
+   "depends_on": "eval:doc.margin_type && doc.price_list_rate && doc.margin_rate_or_amount",
+   "fieldname": "base_rate_with_margin",
+   "fieldtype": "Currency",
+   "label": "Rate With Margin (Company Currency)",
+   "options": "Company:company:default_currency",
+   "print_hide": 1,
+   "read_only": 1
   }
  ],
  "idx": 1,
  "istable": 1,
  "links": [],
- "modified": "2021-01-30 21:43:21.488258",
+ "modified": "2021-02-23 00:59:52.614805",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "Purchase Invoice Item",
diff --git a/erpnext/accounts/doctype/sales_invoice/test_records.json b/erpnext/accounts/doctype/sales_invoice/test_records.json
index ee6419d..e00a58f 100644
--- a/erpnext/accounts/doctype/sales_invoice/test_records.json
+++ b/erpnext/accounts/doctype/sales_invoice/test_records.json
@@ -148,7 +148,7 @@
 	"expense_account": "_Test Account Cost for Goods Sold - _TC",
     "item_code": "_Test Item Home Desktop 100",
     "item_name": "_Test Item Home Desktop 100",
-    "item_tax_template": "_Test Account Excise Duty @ 10",
+    "item_tax_template": "_Test Account Excise Duty @ 10 - _TC",
     "parentfield": "items",
     "price_list_rate": 50,
     "qty": 10,
@@ -276,7 +276,7 @@
 	"expense_account": "_Test Account Cost for Goods Sold - _TC",
     "item_code": "_Test Item Home Desktop 100",
     "item_name": "_Test Item Home Desktop 100",
-    "item_tax_template": "_Test Account Excise Duty @ 10",
+    "item_tax_template": "_Test Account Excise Duty @ 10 - _TC",
     "parentfield": "items",
     "price_list_rate": 62.5,
     "qty": 10,
diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
index 7cd1828..1b95578 100644
--- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
@@ -405,10 +405,10 @@
 		item_row = si.get("items")[0]
 
 		add_items = [
-			(54, '_Test Account Excise Duty @ 12'),
-			(288, '_Test Account Excise Duty @ 15'),
-			(144, '_Test Account Excise Duty @ 20'),
-			(430, '_Test Item Tax Template 1')
+			(54, '_Test Account Excise Duty @ 12 - _TC'),
+			(288, '_Test Account Excise Duty @ 15 - _TC'),
+			(144, '_Test Account Excise Duty @ 20 - _TC'),
+			(430, '_Test Item Tax Template 1 - _TC')
 		]
 		for qty, item_tax_template in add_items:
 			item_row_copy = copy.deepcopy(item_row)
@@ -2077,14 +2077,14 @@
 			item.save()
 
 		item.append("taxes", {
-			"item_tax_template": "_Test Item Tax Template 1",
+			"item_tax_template": "_Test Item Tax Template 1 - _TC",
 			"valid_from": add_days(nowdate(), 1)
 		})
 
 		item.save()
 
 		sales_invoice = create_sales_invoice(item = "_Test Item 2", do_not_save=1)
-		sales_invoice.items[0].item_tax_template = "_Test Item Tax Template 1"
+		sales_invoice.items[0].item_tax_template = "_Test Item Tax Template 1 - _TC"
 		self.assertRaises(frappe.ValidationError, sales_invoice.save)
 
 		item.taxes = []
diff --git a/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json b/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json
index b403c7b..8e6952a 100644
--- a/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json
+++ b/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json
@@ -818,6 +818,7 @@
    "fieldname": "stock_uom_rate",
    "fieldtype": "Currency",
    "label": "Rate of Stock UOM",
+   "no_copy": 1,
    "options": "currency",
    "read_only": 1
   }
@@ -825,7 +826,7 @@
  "idx": 1,
  "istable": 1,
  "links": [],
- "modified": "2021-01-30 21:42:37.796771",
+ "modified": "2021-02-23 01:05:22.123527",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "Sales Invoice Item",
diff --git a/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.py b/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.py
index 76f3c50..0c4a422 100644
--- a/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.py
+++ b/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.py
@@ -240,8 +240,7 @@
 def calculate_values(accounts_by_name, gl_entries_by_account, companies, start_date, filters):
 	for entries in gl_entries_by_account.values():
 		for entry in entries:
-			key = entry.account_number or entry.account_name
-			d = accounts_by_name.get(key)
+			d = accounts_by_name.get(entry.account_name)
 			if d:
 				for company in companies:
 					# check if posting date is within the period
@@ -256,7 +255,8 @@
 	"""accumulate children's values in parent accounts"""
 	for d in reversed(accounts):
 		if d.parent_account:
-			account = d.parent_account.split(' - ')[0].strip()
+			account = d.parent_account_name
+
 			if not accounts_by_name.get(account):
 				continue
 
@@ -267,16 +267,34 @@
 			accounts_by_name[account]["opening_balance"] = \
 				accounts_by_name[account].get("opening_balance", 0.0) + d.get("opening_balance", 0.0)
 
+
 def get_account_heads(root_type, companies, filters):
 	accounts = get_accounts(root_type, filters)
 
 	if not accounts:
 		return None, None
 
+	accounts = update_parent_account_names(accounts)
+
 	accounts, accounts_by_name, parent_children_map = filter_accounts(accounts)
 
 	return accounts, accounts_by_name
 
+def update_parent_account_names(accounts):
+	"""Update parent_account_name in accounts list.
+
+		parent_name is `name` of parent account which could have other prefix
+		of account_number and suffix of company abbr. This function adds key called
+		`parent_account_name` which does not have such prefix/suffix.
+	"""
+	name_to_account_map = { d.name : d.account_name for d in accounts }
+
+	for account in accounts:
+		if account.parent_account:
+			account["parent_account_name"] = name_to_account_map[account.parent_account]
+
+	return accounts
+
 def get_companies(filters):
 	companies = {}
 	all_companies = get_subsidiary_companies(filters.get('company'))
@@ -381,9 +399,9 @@
 			convert_to_presentation_currency(gl_entries, currency_info, filters.get('company'))
 
 		for entry in gl_entries:
-			key = entry.account_number or entry.account_name
-			validate_entries(key, entry, accounts_by_name, accounts)
-			gl_entries_by_account.setdefault(key, []).append(entry)
+			account_name =  entry.account_name
+			validate_entries(account_name, entry, accounts_by_name, accounts)
+			gl_entries_by_account.setdefault(account_name, []).append(entry)
 
 	return gl_entries_by_account
 
@@ -452,8 +470,7 @@
 	parent_children_map = {}
 	accounts_by_name = {}
 	for d in accounts:
-		key = d.account_number or d.account_name
-		accounts_by_name[key] = d
+		accounts_by_name[d.account_name] = d
 		parent_children_map.setdefault(d.parent_account or None, []).append(d)
 
 	filtered_accounts = []
diff --git a/erpnext/accounts/report/general_ledger/general_ledger.py b/erpnext/accounts/report/general_ledger/general_ledger.py
index f735d87..b5d7992 100644
--- a/erpnext/accounts/report/general_ledger/general_ledger.py
+++ b/erpnext/accounts/report/general_ledger/general_ledger.py
@@ -129,6 +129,9 @@
 
 	order_by_statement = "order by posting_date, account, creation"
 
+	if filters.get("include_dimensions"):
+		order_by_statement = "order by posting_date, creation"
+
 	if filters.get("group_by") == _("Group by Voucher"):
 		order_by_statement = "order by posting_date, voucher_type, voucher_no"
 
@@ -142,7 +145,9 @@
 
 	distributed_cost_center_query = ""
 	if filters and filters.get('cost_center'):
-		select_fields_with_percentage = """, debit*(DCC_allocation.percentage_allocation/100) as debit, credit*(DCC_allocation.percentage_allocation/100) as credit, debit_in_account_currency*(DCC_allocation.percentage_allocation/100) as debit_in_account_currency,
+		select_fields_with_percentage = """, debit*(DCC_allocation.percentage_allocation/100) as debit,
+		credit*(DCC_allocation.percentage_allocation/100) as credit,
+		debit_in_account_currency*(DCC_allocation.percentage_allocation/100) as debit_in_account_currency,
 		credit_in_account_currency*(DCC_allocation.percentage_allocation/100) as credit_in_account_currency """
 
 		distributed_cost_center_query = """
@@ -200,7 +205,7 @@
 
 def get_conditions(filters):
 	conditions = []
-	if filters.get("account"):
+	if filters.get("account") and not filters.get("include_dimensions"):
 		lft, rgt = frappe.db.get_value("Account", filters["account"], ["lft", "rgt"])
 		conditions.append("""account in (select name from tabAccount
 			where lft>=%s and rgt<=%s and docstatus<2)""" % (lft, rgt))
@@ -245,17 +250,19 @@
 	if match_conditions:
 		conditions.append(match_conditions)
 
-	accounting_dimensions = get_accounting_dimensions(as_list=False)
+	if filters.get("include_dimensions"):
+		accounting_dimensions = get_accounting_dimensions(as_list=False)
 
-	if accounting_dimensions:
-		for dimension in accounting_dimensions:
-			if filters.get(dimension.fieldname):
-				if frappe.get_cached_value('DocType', dimension.document_type, 'is_tree'):
-					filters[dimension.fieldname] = get_dimension_with_children(dimension.document_type,
-						filters.get(dimension.fieldname))
-					conditions.append("{0} in %({0})s".format(dimension.fieldname))
-				else:
-					conditions.append("{0} in (%({0})s)".format(dimension.fieldname))
+		if accounting_dimensions:
+			for dimension in accounting_dimensions:
+				if not dimension.disabled:
+					if filters.get(dimension.fieldname):
+						if frappe.get_cached_value('DocType', dimension.document_type, 'is_tree'):
+							filters[dimension.fieldname] = get_dimension_with_children(dimension.document_type,
+								filters.get(dimension.fieldname))
+							conditions.append("{0} in %({0})s".format(dimension.fieldname))
+						else:
+							conditions.append("{0} in (%({0})s)".format(dimension.fieldname))
 
 	return "and {}".format(" and ".join(conditions)) if conditions else ""
 
diff --git a/erpnext/accounts/report/tds_computation_summary/tds_computation_summary.py b/erpnext/accounts/report/tds_computation_summary/tds_computation_summary.py
index c7cfee7..a8280c1 100644
--- a/erpnext/accounts/report/tds_computation_summary/tds_computation_summary.py
+++ b/erpnext/accounts/report/tds_computation_summary/tds_computation_summary.py
@@ -55,7 +55,7 @@
 		except IndexError:
 			account = []
 		total_invoiced_amount, tds_deducted = get_invoice_and_tds_amount(supplier.name, account,
-			filters.company, filters.from_date, filters.to_date)
+			filters.company, filters.from_date, filters.to_date, filters.fiscal_year)
 
 		if total_invoiced_amount or tds_deducted:
 			row = [supplier.pan, supplier.name]
@@ -68,7 +68,7 @@
 
 	return out
 
-def get_invoice_and_tds_amount(supplier, account, company, from_date, to_date):
+def get_invoice_and_tds_amount(supplier, account, company, from_date, to_date, fiscal_year):
 	''' calculate total invoice amount and total tds deducted for given supplier  '''
 
 	entries = frappe.db.sql("""
@@ -94,7 +94,9 @@
 		""".format(', '.join(["'%s'" % d for d in vouchers])),
 			(account, from_date, to_date, company))[0][0])
 
-	debit_note_amount = get_debit_note_amount([supplier], from_date, to_date, company=company)
+	date_range_filter = [fiscal_year, from_date, to_date]
+
+	debit_note_amount = get_debit_note_amount([supplier], date_range_filter, company=company)
 
 	total_invoiced_amount = supplier_credit_amount + tds_deducted - debit_note_amount
 
diff --git a/erpnext/buying/doctype/purchase_order/test_purchase_order.py b/erpnext/buying/doctype/purchase_order/test_purchase_order.py
index d568ef1..02d4865 100644
--- a/erpnext/buying/doctype/purchase_order/test_purchase_order.py
+++ b/erpnext/buying/doctype/purchase_order/test_purchase_order.py
@@ -231,12 +231,12 @@
 		new_item_with_tax = frappe.get_doc("Item", "Test Item with Tax")
 
 		new_item_with_tax.append("taxes", {
-			"item_tax_template": "Test Update Items Template",
+			"item_tax_template": "Test Update Items Template - _TC",
 			"valid_from": nowdate()
 		})
 		new_item_with_tax.save()
 
-		tax_template = "_Test Account Excise Duty @ 10"
+		tax_template = "_Test Account Excise Duty @ 10 - _TC"
 		item =  "_Test Item Home Desktop 100"
 		if not frappe.db.exists("Item Tax", {"parent":item, "item_tax_template":tax_template}):
 			item_doc = frappe.get_doc("Item", item)
@@ -287,7 +287,7 @@
 		po.cancel()
 		po.delete()
 		new_item_with_tax.delete()
-		frappe.get_doc("Item Tax Template", "Test Update Items Template").delete()
+		frappe.get_doc("Item Tax Template", "Test Update Items Template - _TC").delete()
 
 	def test_update_child_uom_conv_factor_change(self):
 		po = create_purchase_order(item_code="_Test FG Item", is_subcontracted="Yes")
diff --git a/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json b/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json
index eba52f2..51a38e2 100644
--- a/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json
+++ b/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json
@@ -51,6 +51,7 @@
   "warehouse_and_reference",
   "warehouse",
   "actual_qty",
+  "company_total_stock",
   "material_request",
   "material_request_item",
   "sales_order",
@@ -744,13 +745,19 @@
    "label": "Available Qty at Warehouse",
    "print_hide": 1,
    "read_only": 1
+  },
+  {
+   "fieldname": "company_total_stock",
+   "fieldtype": "Float",
+   "label": "Available Qty at Company",
+   "read_only": 1
   }
  ],
  "idx": 1,
  "index_web_pages_for_search": 1,
  "istable": 1,
  "links": [],
- "modified": "2021-03-15 10:10:16.342693",
+ "modified": "2021-03-22 11:20:00.121296",
  "modified_by": "Administrator",
  "module": "Buying",
  "name": "Purchase Order Item",
diff --git a/erpnext/controllers/buying_controller.py b/erpnext/controllers/buying_controller.py
index e469838..219d529 100644
--- a/erpnext/controllers/buying_controller.py
+++ b/erpnext/controllers/buying_controller.py
@@ -278,7 +278,7 @@
 
 		if self.is_subcontracted == "Yes":
 			if self.doctype in ["Purchase Receipt", "Purchase Invoice"] and not self.supplier_warehouse:
-				frappe.throw(_("Supplier Warehouse mandatory for sub-contracted Purchase Receipt"))
+				frappe.throw(_("Supplier Warehouse mandatory for sub-contracted {0}").format(self.doctype))
 
 			for item in self.get("items"):
 				if item in self.sub_contracted_items and not item.bom:
diff --git a/erpnext/controllers/stock_controller.py b/erpnext/controllers/stock_controller.py
index e0031c9..11ac703 100644
--- a/erpnext/controllers/stock_controller.py
+++ b/erpnext/controllers/stock_controller.py
@@ -406,7 +406,8 @@
 	def set_rate_of_stock_uom(self):
 		if self.doctype in ["Purchase Receipt", "Purchase Invoice", "Purchase Order", "Sales Invoice", "Sales Order", "Delivery Note", "Quotation"]:
 			for d in self.get("items"):
-				d.stock_uom_rate = d.rate / d.conversion_factor
+				if d.conversion_factor:
+					d.stock_uom_rate = d.rate / d.conversion_factor
 
 	def validate_internal_transfer(self):
 		if self.doctype in ('Sales Invoice', 'Delivery Note', 'Purchase Invoice', 'Purchase Receipt') \
diff --git a/erpnext/controllers/taxes_and_totals.py b/erpnext/controllers/taxes_and_totals.py
index 10271cb..aab5770 100644
--- a/erpnext/controllers/taxes_and_totals.py
+++ b/erpnext/controllers/taxes_and_totals.py
@@ -109,7 +109,7 @@
 					elif item.discount_amount and item.pricing_rules:
 						item.rate =  item.price_list_rate - item.discount_amount
 
-				if item.doctype in ['Quotation Item', 'Sales Order Item', 'Delivery Note Item', 'Sales Invoice Item', 'POS Invoice Item']:
+				if item.doctype in ['Quotation Item', 'Sales Order Item', 'Delivery Note Item', 'Sales Invoice Item', 'POS Invoice Item', 'Purchase Invoice Item', 'Purchase Order Item', 'Purchase Receipt Item']:
 					item.rate_with_margin, item.base_rate_with_margin = self.calculate_margin(item)
 					if flt(item.rate_with_margin) > 0:
 						item.rate = flt(item.rate_with_margin * (1.0 - (item.discount_percentage / 100.0)), item.precision("rate"))
diff --git a/erpnext/education/api.py b/erpnext/education/api.py
index 948e7cc..afa0be9 100644
--- a/erpnext/education/api.py
+++ b/erpnext/education/api.py
@@ -36,6 +36,7 @@
 	student.save()
 	program_enrollment = frappe.new_doc("Program Enrollment")
 	program_enrollment.student = student.name
+	program_enrollment.student_category = student.student_category
 	program_enrollment.student_name = student.title
 	program_enrollment.program = frappe.db.get_value("Student Applicant", source_name, "program")
 	frappe.publish_realtime('enroll_student_progress', {"progress": [2, 4]}, user=frappe.session.user)
diff --git a/erpnext/education/doctype/program_enrollment_tool/program_enrollment_tool.py b/erpnext/education/doctype/program_enrollment_tool/program_enrollment_tool.py
index 9f8f9f4..8180102 100644
--- a/erpnext/education/doctype/program_enrollment_tool/program_enrollment_tool.py
+++ b/erpnext/education/doctype/program_enrollment_tool/program_enrollment_tool.py
@@ -30,7 +30,7 @@
 					.format(condition), self.as_dict(), as_dict=1)
 			elif self.get_students_from == "Program Enrollment":
 				condition2 = 'and student_batch_name=%(student_batch)s' if self.student_batch else " "
-				students = frappe.db.sql('''select student, student_name, student_batch_name from `tabProgram Enrollment`
+				students = frappe.db.sql('''select student, student_name, student_batch_name, student_category from `tabProgram Enrollment`
 					where program=%(program)s and academic_year=%(academic_year)s {0} {1} and docstatus != 2'''
 					.format(condition, condition2), self.as_dict(), as_dict=1)
 
@@ -57,6 +57,7 @@
 				prog_enrollment = frappe.new_doc("Program Enrollment")
 				prog_enrollment.student = stud.student
 				prog_enrollment.student_name = stud.student_name
+				prog_enrollment.student_category = stud.student_category
 				prog_enrollment.program = self.new_program
 				prog_enrollment.academic_year = self.new_academic_year
 				prog_enrollment.academic_term = self.new_academic_term
diff --git a/erpnext/education/doctype/student_applicant/student_applicant.json b/erpnext/education/doctype/student_applicant/student_applicant.json
index 6df9b9a..95f9224 100644
--- a/erpnext/education/doctype/student_applicant/student_applicant.json
+++ b/erpnext/education/doctype/student_applicant/student_applicant.json
@@ -11,6 +11,7 @@
   "middle_name",
   "last_name",
   "program",
+  "student_category",
   "lms_only",
   "paid",
   "column_break_8",
@@ -257,12 +258,18 @@
    "options": "Student Applicant",
    "print_hide": 1,
    "read_only": 1
+  },
+  {
+   "fieldname": "student_category",
+   "fieldtype": "Link",
+   "label": "Student Category",
+   "options": "Student Category"
   }
  ],
  "image_field": "image",
  "is_submittable": 1,
  "links": [],
- "modified": "2020-10-05 13:59:45.631647",
+ "modified": "2021-03-01 23:00:25.119241",
  "modified_by": "Administrator",
  "module": "Education",
  "name": "Student Applicant",
diff --git a/erpnext/erpnext_integrations/doctype/shopify_settings/test_shopify_settings.py b/erpnext/erpnext_integrations/doctype/shopify_settings/test_shopify_settings.py
index 30fa23c..74ad456 100644
--- a/erpnext/erpnext_integrations/doctype/shopify_settings/test_shopify_settings.py
+++ b/erpnext/erpnext_integrations/doctype/shopify_settings/test_shopify_settings.py
@@ -17,8 +17,7 @@
 		frappe.set_user("Administrator")
 
 		# use the fixture data
-		import_doc(path=frappe.get_app_path("erpnext", "erpnext_integrations/doctype/shopify_settings/test_data/custom_field.json"),
-			ignore_links=True, overwrite=True)
+		import_doc(frappe.get_app_path("erpnext", "erpnext_integrations/doctype/shopify_settings/test_data/custom_field.json"))
 
 		frappe.reload_doctype("Customer")
 		frappe.reload_doctype("Sales Order")
diff --git a/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.js b/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.js
index ff51646..b55d5d6 100644
--- a/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.js
+++ b/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.js
@@ -364,7 +364,7 @@
 	let age = new Date();
 	age.setTime(ageMS);
 	let years =  age.getFullYear() - 1970;
-	return  years + ' Year(s) ' + age.getMonth() + ' Month(s) ' + age.getDate() + ' Day(s)';
+	return `${years} ${__('Years(s)')} ${age.getMonth()} ${__('Month(s)')} ${age.getDate()} ${__('Day(s)')}`;
 };
 
 // List Stock items
diff --git a/erpnext/healthcare/doctype/lab_test/lab_test.js b/erpnext/healthcare/doctype/lab_test/lab_test.js
index f1634c1..bb7976c 100644
--- a/erpnext/healthcare/doctype/lab_test/lab_test.js
+++ b/erpnext/healthcare/doctype/lab_test/lab_test.js
@@ -258,5 +258,5 @@
 	var age = new Date();
 	age.setTime(ageMS);
 	var years = age.getFullYear() - 1970;
-	return years + ' Year(s) ' + age.getMonth() + ' Month(s) ' + age.getDate() + ' Day(s)';
+	return `${years} ${__('Years(s)')} ${age.getMonth()} ${__('Month(s)')} ${age.getDate()} ${__('Day(s)')}`;
 };
diff --git a/erpnext/healthcare/doctype/patient/patient.js b/erpnext/healthcare/doctype/patient/patient.js
index 490f247..bce42e5 100644
--- a/erpnext/healthcare/doctype/patient/patient.js
+++ b/erpnext/healthcare/doctype/patient/patient.js
@@ -46,11 +46,11 @@
 		}
 	},
 	onload: function (frm) {
-		if(!frm.doc.dob){
+		if (!frm.doc.dob) {
 			$(frm.fields_dict['age_html'].wrapper).html('');
 		}
-		if(frm.doc.dob){
-			$(frm.fields_dict['age_html'].wrapper).html('AGE : ' + get_age(frm.doc.dob));
+		if (frm.doc.dob) {
+			$(frm.fields_dict['age_html'].wrapper).html(`${__('AGE')} : ${get_age(frm.doc.dob)}`);
 		}
 	}
 });
@@ -65,7 +65,7 @@
 		}
 		else {
 			let age_str = get_age(frm.doc.dob);
-			$(frm.fields_dict['age_html'].wrapper).html('AGE : ' + age_str);
+			$(frm.fields_dict['age_html'].wrapper).html(`${__('AGE')} : ${age_str}`);
 		}
 	}
 	else {
diff --git a/erpnext/healthcare/doctype/patient/patient.py b/erpnext/healthcare/doctype/patient/patient.py
index 63dd8d4..8603f97 100644
--- a/erpnext/healthcare/doctype/patient/patient.py
+++ b/erpnext/healthcare/doctype/patient/patient.py
@@ -108,7 +108,7 @@
 		if self.dob:
 			dob = getdate(self.dob)
 			age = dateutil.relativedelta.relativedelta(getdate(), dob)
-			age_str = str(age.years) + ' year(s) ' + str(age.months) + ' month(s) ' + str(age.days) + ' day(s)'
+			age_str = str(age.years) + ' ' + _("Years(s)") + ' ' + str(age.months) + ' ' + _("Month(s)") + ' ' + str(age.days) + ' ' + _("Day(s)")
 		return age_str
 
 	def invoice_patient_registration(self):
diff --git a/erpnext/healthcare/doctype/patient_appointment/patient_appointment.js b/erpnext/healthcare/doctype/patient_appointment/patient_appointment.js
index 0354733..2976ef1 100644
--- a/erpnext/healthcare/doctype/patient_appointment/patient_appointment.js
+++ b/erpnext/healthcare/doctype/patient_appointment/patient_appointment.js
@@ -596,5 +596,5 @@
 	let age = new Date();
 	age.setTime(ageMS);
 	let years =  age.getFullYear() - 1970;
-	return  years + ' Year(s) ' + age.getMonth() + ' Month(s) ' + age.getDate() + ' Day(s)';
+	return `${years} ${__('Years(s)')} ${age.getMonth()} ${__('Month(s)')} ${age.getDate()} ${__('Day(s)')}`;
 };
diff --git a/erpnext/healthcare/doctype/patient_encounter/patient_encounter.js b/erpnext/healthcare/doctype/patient_encounter/patient_encounter.js
index e960f0a..aaeaa69 100644
--- a/erpnext/healthcare/doctype/patient_encounter/patient_encounter.js
+++ b/erpnext/healthcare/doctype/patient_encounter/patient_encounter.js
@@ -358,5 +358,5 @@
 	let age = new Date();
 	age.setTime(ageMS);
 	let years =  age.getFullYear() - 1970;
-	return  years + ' Year(s) ' + age.getMonth() + ' Month(s) ' + age.getDate() + ' Day(s)';
+	return `${years} ${__('Years(s)')} ${age.getMonth()} ${__('Month(s)')} ${age.getDate()} ${__('Day(s)')}`;
 };
diff --git a/erpnext/healthcare/doctype/sample_collection/sample_collection.js b/erpnext/healthcare/doctype/sample_collection/sample_collection.js
index 0390391..ddf8285 100644
--- a/erpnext/healthcare/doctype/sample_collection/sample_collection.js
+++ b/erpnext/healthcare/doctype/sample_collection/sample_collection.js
@@ -36,5 +36,5 @@
 	var	age = new Date();
 	age.setTime(ageMS);
 	var	years =  age.getFullYear() - 1970;
-	return  years + ' Year(s) ' + age.getMonth() + ' Month(s) ' + age.getDate() + ' Day(s)';
+	return `${years} ${__('Years(s)')} ${age.getMonth()} ${__('Month(s)')} ${age.getDate()} ${__('Day(s)')}`;
 };
diff --git a/erpnext/hooks.py b/erpnext/hooks.py
index f87769c..4b3597a 100644
--- a/erpnext/hooks.py
+++ b/erpnext/hooks.py
@@ -361,13 +361,13 @@
 		"erpnext.hr.utils.generate_leave_encashment",
 		"erpnext.hr.utils.allocate_earned_leaves",
 		"erpnext.hr.utils.grant_leaves_automatically",
-		"erpnext.loan_management.doctype.loan_security_shortfall.loan_security_shortfall.create_process_loan_security_shortfall",
-		"erpnext.loan_management.doctype.loan_interest_accrual.loan_interest_accrual.process_loan_interest_accrual_for_term_loans",
+		"erpnext.loan_management.doctype.process_loan_security_shortfall.process_loan_security_shortfall.create_process_loan_security_shortfall",
+		"erpnext.loan_management.doctype.process_loan_interest_accrual.process_loan_interest_accrual.process_loan_interest_accrual_for_term_loans",
 		"erpnext.crm.doctype.lead.lead.daily_open_lead"
 	],
 	"monthly_long": [
 		"erpnext.accounts.deferred_revenue.process_deferred_accounting",
-		"erpnext.loan_management.doctype.loan_interest_accrual.loan_interest_accrual.process_loan_interest_accrual_for_demand_loans"
+		"erpnext.loan_management.doctype.process_loan_interest_accrual.process_loan_interest_accrual.process_loan_interest_accrual_for_demand_loans"
 	]
 }
 
diff --git a/erpnext/hr/doctype/attendance/attendance.py b/erpnext/hr/doctype/attendance/attendance.py
index 373b940..18a4fe5 100644
--- a/erpnext/hr/doctype/attendance/attendance.py
+++ b/erpnext/hr/doctype/attendance/attendance.py
@@ -131,6 +131,10 @@
 		data = json.loads(data)
 	data = frappe._dict(data)
 	company = frappe.get_value('Employee', data.employee, 'company')
+	if not data.unmarked_days:
+		frappe.throw(_("Please select a date."))
+		return
+
 	for date in data.unmarked_days:
 		doc_dict = {
 			'doctype': 'Attendance',
diff --git a/erpnext/hr/doctype/attendance/attendance_list.js b/erpnext/hr/doctype/attendance/attendance_list.js
index 6df3dbd..0c7eafe 100644
--- a/erpnext/hr/doctype/attendance/attendance_list.js
+++ b/erpnext/hr/doctype/attendance/attendance_list.js
@@ -12,7 +12,7 @@
 	onload: function(list_view) {
 		let me = this;
 		const months = moment.months()
-		list_view.page.add_inner_button( __("Mark Attendance"), function(){
+		list_view.page.add_inner_button( __("Mark Attendance"), function() {
 			let dialog = new frappe.ui.Dialog({
 				title: __("Mark Attendance"),
 				fields: [
@@ -22,11 +22,12 @@
 						fieldtype: 'Link',
 						options: 'Employee',
 						reqd: 1,
-						onchange: function(){
+						onchange: function() {
 							dialog.set_df_property("unmarked_days", "hidden", 1);
 							dialog.set_df_property("status", "hidden", 1);
 							dialog.set_df_property("month", "value", '');
 							dialog.set_df_property("unmarked_days", "options", []);
+							dialog.no_unmarked_days_left = false;
 						}
 					},
 					{
@@ -35,13 +36,18 @@
 						fieldname: "month",
 						options: months,
 						reqd: 1,
-						onchange: function(){
+						onchange: function() {
 							if(dialog.fields_dict.employee.value && dialog.fields_dict.month.value) {
 								dialog.set_df_property("status", "hidden", 0);
 								dialog.set_df_property("unmarked_days", "options", []);
+								dialog.no_unmarked_days_left = false;
 								me.get_multi_select_options(dialog.fields_dict.employee.value, dialog.fields_dict.month.value).then(options =>{
-									dialog.set_df_property("unmarked_days", "hidden", 0);
-									dialog.set_df_property("unmarked_days", "options", options);
+									if (options.length > 0) {
+										dialog.set_df_property("unmarked_days", "hidden", 0);
+										dialog.set_df_property("unmarked_days", "options", options);
+									} else {
+										dialog.no_unmarked_days_left = true;
+									}
 								});
 							}
 						}
@@ -64,21 +70,25 @@
 						hidden: 1
 					},
 				],
-				primary_action(data){
-					frappe.confirm(__('Mark attendance as <b>' + data.status + '</b> for <b>' + data.month +'</b>' + ' on selected dates?'), () => {
-						frappe.call({
-							method: "erpnext.hr.doctype.attendance.attendance.mark_bulk_attendance",
-							args: {
-								data : data
-							},
-							callback: function(r) {
-								if(r.message === 1) {
-									frappe.show_alert({message:__("Attendance Marked"), indicator:'blue'});
-									cur_dialog.hide();
+				primary_action(data)  {
+					if (cur_dialog.no_unmarked_days_left) {
+						frappe.msgprint(__("Attendance for the month of {0} , has already been marked for the Employee {1}",[dialog.fields_dict.month.value, dialog.fields_dict.employee.value]));
+					} else {
+						frappe.confirm(__('Mark attendance as {0} for {1} on selected dates?', [data.status,data.month]), () => {
+							frappe.call({
+								method: "erpnext.hr.doctype.attendance.attendance.mark_bulk_attendance",
+								args: {
+									data: data
+								},
+								callback: function(r) {
+									if (r.message === 1) {
+										frappe.show_alert({message: __("Attendance Marked"), indicator: 'blue'});
+										cur_dialog.hide();
+									}
 								}
-							}
+							});
 						});
-					});
+					}
 					dialog.hide();
 					list_view.refresh();
 				},
diff --git a/erpnext/hr/doctype/employee/employee.json b/erpnext/hr/doctype/employee/employee.json
index dc2aaa4..5123d6a 100644
--- a/erpnext/hr/doctype/employee/employee.json
+++ b/erpnext/hr/doctype/employee/employee.json
@@ -813,7 +813,7 @@
  "idx": 24,
  "image_field": "image",
  "links": [],
- "modified": "2021-01-01 16:54:33.477439",
+ "modified": "2021-01-02 16:54:33.477439",
  "modified_by": "Administrator",
  "module": "HR",
  "name": "Employee",
diff --git a/erpnext/hr/doctype/employee/test_employee.py b/erpnext/hr/doctype/employee/test_employee.py
index c0e614a..7d652a7 100644
--- a/erpnext/hr/doctype/employee/test_employee.py
+++ b/erpnext/hr/doctype/employee/test_employee.py
@@ -48,6 +48,7 @@
 		self.assertRaises(EmployeeLeftValidationError, employee1_doc.save)
 
 def make_employee(user, company=None, **kwargs):
+	""
 	if not frappe.db.get_value("User", user):
 		frappe.get_doc({
 			"doctype": "User",
diff --git a/erpnext/hr/utils.py b/erpnext/hr/utils.py
index d57ef59..0c4c1ca 100644
--- a/erpnext/hr/utils.py
+++ b/erpnext/hr/utils.py
@@ -1,16 +1,19 @@
 # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
 # License: GNU General Public License v3. See license.txt
 
-from __future__ import unicode_literals
-import frappe, erpnext
-from frappe import _
-from frappe.utils import formatdate, format_datetime, getdate, get_datetime, nowdate, flt, cstr, add_days, today
-from frappe.model.document import Document
-from frappe.desk.form import assign_to
+import erpnext
+import frappe
 from erpnext.hr.doctype.employee.employee import get_holiday_list_for_employee
+from frappe import _
+from frappe.desk.form import assign_to
+from frappe.model.document import Document
+from frappe.utils import (add_days, cstr, flt, format_datetime, formatdate,
+	get_datetime, getdate, nowdate, today, unique)
+
 
 class DuplicateDeclarationError(frappe.ValidationError): pass
 
+
 class EmployeeBoardingController(Document):
 	'''
 		Create the project and the task for the boarding process
@@ -48,27 +51,38 @@
 				continue
 
 			task = frappe.get_doc({
-					"doctype": "Task",
-					"project": self.project,
-					"subject": activity.activity_name + " : " + self.employee_name,
-					"description": activity.description,
-					"department": self.department,
-					"company": self.company,
-					"task_weight": activity.task_weight
-				}).insert(ignore_permissions=True)
+				"doctype": "Task",
+				"project": self.project,
+				"subject": activity.activity_name + " : " + self.employee_name,
+				"description": activity.description,
+				"department": self.department,
+				"company": self.company,
+				"task_weight": activity.task_weight
+			}).insert(ignore_permissions=True)
 			activity.db_set("task", task.name)
+
 			users = [activity.user] if activity.user else []
 			if activity.role:
-				user_list = frappe.db.sql_list('''select distinct(parent) from `tabHas Role`
-					where parenttype='User' and role=%s''', activity.role)
-				users = users + user_list
+				user_list = frappe.db.sql_list('''
+					SELECT
+						DISTINCT(has_role.parent)
+					FROM
+						`tabHas Role` has_role
+							LEFT JOIN `tabUser` user
+								ON has_role.parent = user.name
+					WHERE
+						has_role.parenttype = 'User'
+							AND user.enabled = 1
+							AND has_role.role = %s
+				''', activity.role)
+				users = unique(users + user_list)
 
 				if "Administrator" in users:
 					users.remove("Administrator")
 
 			# assign the task the users
 			if users:
-				self.assign_task_to_users(task, set(users))
+				self.assign_task_to_users(task, users)
 
 	def assign_task_to_users(self, task, users):
 		for user in users:
diff --git a/erpnext/non_profit/doctype/membership_settings/__init__.py b/erpnext/non_profit/doctype/donation/__init__.py
similarity index 100%
copy from erpnext/non_profit/doctype/membership_settings/__init__.py
copy to erpnext/non_profit/doctype/donation/__init__.py
diff --git a/erpnext/non_profit/doctype/donation/donation.js b/erpnext/non_profit/doctype/donation/donation.js
new file mode 100644
index 0000000..10e8220
--- /dev/null
+++ b/erpnext/non_profit/doctype/donation/donation.js
@@ -0,0 +1,26 @@
+// Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+frappe.ui.form.on('Donation', {
+	refresh: function(frm) {
+		if (frm.doc.docstatus === 1 && !frm.doc.paid) {
+			frm.add_custom_button(__('Create Payment Entry'), function() {
+				frm.events.make_payment_entry(frm);
+			});
+		}
+	},
+
+	make_payment_entry: function(frm) {
+		return frappe.call({
+			method: 'erpnext.accounts.doctype.payment_entry.payment_entry.get_payment_entry',
+			args: {
+				'dt': frm.doc.doctype,
+				'dn': frm.doc.name
+			},
+			callback: function(r) {
+				var doc = frappe.model.sync(r.message);
+				frappe.set_route('Form', doc[0].doctype, doc[0].name);
+			}
+		});
+	},
+});
diff --git a/erpnext/non_profit/doctype/donation/donation.json b/erpnext/non_profit/doctype/donation/donation.json
new file mode 100644
index 0000000..6759569
--- /dev/null
+++ b/erpnext/non_profit/doctype/donation/donation.json
@@ -0,0 +1,156 @@
+{
+ "actions": [],
+ "autoname": "naming_series:",
+ "creation": "2021-02-17 10:28:52.645731",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "naming_series",
+  "donor",
+  "donor_name",
+  "email",
+  "column_break_4",
+  "company",
+  "date",
+  "payment_details_section",
+  "paid",
+  "amount",
+  "mode_of_payment",
+  "razorpay_payment_id",
+  "amended_from"
+ ],
+ "fields": [
+  {
+   "fieldname": "donor",
+   "fieldtype": "Link",
+   "label": "Donor",
+   "options": "Donor",
+   "reqd": 1
+  },
+  {
+   "fetch_from": "donor.donor_name",
+   "fieldname": "donor_name",
+   "fieldtype": "Data",
+   "in_list_view": 1,
+   "in_standard_filter": 1,
+   "label": "Donor Name",
+   "read_only": 1
+  },
+  {
+   "fetch_from": "donor.email",
+   "fieldname": "email",
+   "fieldtype": "Data",
+   "in_list_view": 1,
+   "in_standard_filter": 1,
+   "label": "Email",
+   "read_only": 1
+  },
+  {
+   "fieldname": "column_break_4",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "date",
+   "fieldtype": "Date",
+   "label": "Date",
+   "reqd": 1
+  },
+  {
+   "fieldname": "payment_details_section",
+   "fieldtype": "Section Break",
+   "label": "Payment Details"
+  },
+  {
+   "fieldname": "amount",
+   "fieldtype": "Currency",
+   "label": "Amount",
+   "reqd": 1
+  },
+  {
+   "fieldname": "mode_of_payment",
+   "fieldtype": "Link",
+   "label": "Mode of Payment",
+   "options": "Mode of Payment"
+  },
+  {
+   "fieldname": "razorpay_payment_id",
+   "fieldtype": "Data",
+   "label": "Razorpay Payment ID",
+   "read_only": 1
+  },
+  {
+   "fieldname": "naming_series",
+   "fieldtype": "Select",
+   "label": "Naming Series",
+   "options": "NPO-DTN-.YYYY.-"
+  },
+  {
+   "default": "0",
+   "fieldname": "paid",
+   "fieldtype": "Check",
+   "in_list_view": 1,
+   "in_standard_filter": 1,
+   "label": "Paid"
+  },
+  {
+   "fieldname": "company",
+   "fieldtype": "Link",
+   "label": "Company",
+   "options": "Company",
+   "reqd": 1
+  },
+  {
+   "fieldname": "amended_from",
+   "fieldtype": "Link",
+   "label": "Amended From",
+   "no_copy": 1,
+   "options": "Donation",
+   "print_hide": 1,
+   "read_only": 1
+  }
+ ],
+ "index_web_pages_for_search": 1,
+ "is_submittable": 1,
+ "links": [],
+ "modified": "2021-03-11 10:53:11.269005",
+ "modified_by": "Administrator",
+ "module": "Non Profit",
+ "name": "Donation",
+ "owner": "Administrator",
+ "permissions": [
+  {
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "export": 1,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "System Manager",
+   "select": 1,
+   "share": 1,
+   "submit": 1,
+   "write": 1
+  },
+  {
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "export": 1,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "Non Profit Manager",
+   "select": 1,
+   "share": 1,
+   "submit": 1,
+   "write": 1
+  }
+ ],
+ "search_fields": "donor_name, email",
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "title_field": "donor_name",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/non_profit/doctype/donation/donation.py b/erpnext/non_profit/doctype/donation/donation.py
new file mode 100644
index 0000000..e947588
--- /dev/null
+++ b/erpnext/non_profit/doctype/donation/donation.py
@@ -0,0 +1,215 @@
+# -*- 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
+import six
+import json
+from frappe.model.document import Document
+from frappe import _
+from frappe.utils import getdate, flt, get_link_to_form
+from frappe.email import sendmail_to_system_managers
+from erpnext.non_profit.doctype.membership.membership import verify_signature
+
+class Donation(Document):
+	def validate(self):
+		if not self.donor or not frappe.db.exists('Donor', self.donor):
+			# for web forms
+			user_type = frappe.db.get_value('User', frappe.session.user, 'user_type')
+			if user_type == 'Website User':
+				self.create_donor_for_website_user()
+			else:
+				frappe.throw(_('Please select a Member'))
+
+	def create_donor_for_website_user(self):
+		donor_name = frappe.get_value('Donor', dict(email=frappe.session.user))
+
+		if not donor_name:
+			user = frappe.get_doc('User', frappe.session.user)
+			donor = frappe.get_doc(dict(
+				doctype='Donor',
+				donor_type=self.get('donor_type'),
+				email=frappe.session.user,
+				member_name=user.get_fullname()
+			)).insert(ignore_permissions=True)
+			donor_name = donor.name
+
+		if self.get('__islocal'):
+			self.donor = donor_name
+
+	def on_payment_authorized(self, *args, **kwargs):
+		self.load_from_db()
+		self.create_payment_entry()
+
+	def create_payment_entry(self):
+		settings = frappe.get_doc('Non Profit Settings')
+		if not settings.automate_donation_payment_entries:
+			return
+
+		if not settings.donation_payment_account:
+			frappe.throw(_('You need to set <b>Payment Account</b> for Donation in {0}').format(
+				get_link_to_form('Non Profit Settings', 'Non Profit Settings')))
+
+		from erpnext.accounts.doctype.payment_entry.payment_entry import get_payment_entry
+
+		frappe.flags.ignore_account_permission = True
+		pe = get_payment_entry(dt=self.doctype, dn=self.name)
+		frappe.flags.ignore_account_permission = False
+		pe.paid_from = settings.donation_debit_account
+		pe.paid_to = settings.donation_payment_account
+		pe.reference_no = self.name
+		pe.reference_date = getdate()
+		pe.flags.ignore_mandatory = True
+		pe.insert()
+		pe.submit()
+
+
+@frappe.whitelist(allow_guest=True)
+def capture_razorpay_donations(*args, **kwargs):
+	"""
+		Creates Donation from Razorpay Webhook Request Data on payment.captured event
+		Creates Donor from email if not found
+	"""
+	data = frappe.request.get_data(as_text=True)
+
+	try:
+		verify_signature(data, endpoint='Donation')
+	except Exception as e:
+		log = frappe.log_error(e, 'Donation Webhook Verification Error')
+		notify_failure(log)
+		return { 'status': 'Failed', 'reason': e }
+
+	if isinstance(data, six.string_types):
+		data = json.loads(data)
+	data = frappe._dict(data)
+
+	payment = data.payload.get('payment', {}).get('entity', {})
+	payment = frappe._dict(payment)
+
+	try:
+		if not data.event == 'payment.captured':
+			return
+
+		donor = get_donor(payment.email)
+		if not donor:
+			donor = create_donor(payment)
+
+		donation = create_donation(donor, payment)
+		donation.run_method('create_payment_entry')
+
+	except Exception as e:
+		message = '{0}\n\n{1}\n\n{2}: {3}'.format(e, frappe.get_traceback(), _('Payment ID'), payment.id)
+		log = frappe.log_error(message, _('Error creating donation entry for {0}').format(donor.name))
+		notify_failure(log)
+		return { 'status': 'Failed', 'reason': e }
+
+	return { 'status': 'Success' }
+
+
+def create_donation(donor, payment):
+	if not frappe.db.exists('Mode of Payment', payment.method):
+		create_mode_of_payment(payment.method)
+
+	company = get_company_for_donations()
+	donation = frappe.get_doc({
+		'doctype': 'Donation',
+		'company': company,
+		'donor': donor.name,
+		'donor_name': donor.donor_name,
+		'email': donor.email,
+		'date': getdate(),
+		'amount': flt(payment.amount),
+		'mode_of_payment': payment.method,
+		'razorpay_payment_id': payment.id
+	}).insert(ignore_mandatory=True)
+
+	donation.submit()
+	return donation
+
+
+def get_donor(email):
+	donors = frappe.get_all('Donor',
+		filters={'email': email},
+		order_by='creation desc')
+
+	try:
+		return frappe.get_doc('Donor', donors[0]['name'])
+	except Exception:
+		return None
+
+
+@frappe.whitelist()
+def create_donor(payment):
+	donor_details = frappe._dict(payment)
+	donor_type = frappe.db.get_single_value('Non Profit Settings', 'default_donor_type')
+
+	donor = frappe.new_doc('Donor')
+	donor.update({
+		'donor_name': donor_details.email,
+		'donor_type': donor_type,
+		'email': donor_details.email,
+		'contact': donor_details.contact
+	})
+
+	if donor_details.get('notes'):
+		donor = get_additional_notes(donor, donor_details)
+
+	donor.insert(ignore_mandatory=True)
+	return donor
+
+
+def get_company_for_donations():
+	company = frappe.db.get_single_value('Non Profit Settings', 'donation_company')
+	if not company:
+		from erpnext.healthcare.setup import get_company
+		company = get_company()
+	return company
+
+
+def get_additional_notes(donor, donor_details):
+	if type(donor_details.notes) == dict:
+		for k, v in donor_details.notes.items():
+			notes = '\n'.join('{}: {}'.format(k, v))
+
+			# extract donor name from notes
+			if 'name' in k.lower():
+				donor.update({
+					'donor_name': donor_details.notes.get(k)
+				})
+
+			# extract pan from notes
+			if 'pan' in k.lower():
+				donor.update({
+					'pan_number': donor_details.notes.get(k)
+				})
+
+		donor.add_comment('Comment', notes)
+
+	elif type(donor_details.notes) == str:
+		donor.add_comment('Comment', donor_details.notes)
+
+	return donor
+
+
+def create_mode_of_payment(method):
+	frappe.get_doc({
+		'doctype': 'Mode of Payment',
+		'mode_of_payment': method
+	}).insert(ignore_mandatory=True)
+
+
+def notify_failure(log):
+	try:
+		content = '''
+			Dear System Manager,
+			Razorpay webhook for creating donation failed due to some reason.
+			Please check the error log linked below
+			Error Log: {0}
+			Regards, Administrator
+		'''.format(get_link_to_form('Error Log', log.name))
+
+		sendmail_to_system_managers(_('[Important] [ERPNext] Razorpay donation webhook failed, please check.'), content)
+	except Exception:
+		pass
+
diff --git a/erpnext/non_profit/doctype/donation/donation_dashboard.py b/erpnext/non_profit/doctype/donation/donation_dashboard.py
new file mode 100644
index 0000000..7e25c8d
--- /dev/null
+++ b/erpnext/non_profit/doctype/donation/donation_dashboard.py
@@ -0,0 +1,16 @@
+from __future__ import unicode_literals
+from frappe import _
+
+def get_data():
+	return {
+		'fieldname': 'donation',
+		'non_standard_fieldnames': {
+			'Payment Entry': 'reference_name'
+		},
+		'transactions': [
+			{
+				'label': _('Payment'),
+				'items': ['Payment Entry']
+			}
+		]
+	}
\ No newline at end of file
diff --git a/erpnext/non_profit/doctype/donation/test_donation.py b/erpnext/non_profit/doctype/donation/test_donation.py
new file mode 100644
index 0000000..c6a534d
--- /dev/null
+++ b/erpnext/non_profit/doctype/donation/test_donation.py
@@ -0,0 +1,76 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors
+# See license.txt
+from __future__ import unicode_literals
+
+import frappe
+import unittest
+from erpnext.non_profit.doctype.donation.donation import create_donation
+
+class TestDonation(unittest.TestCase):
+	def setUp(self):
+		create_donor_type()
+		settings = frappe.get_doc('Non Profit Settings')
+		settings.company = '_Test Company'
+		settings.donation_company = '_Test Company'
+		settings.default_donor_type = '_Test Donor'
+		settings.automate_donation_payment_entries = 1
+		settings.donation_debit_account = 'Debtors - _TC'
+		settings.donation_payment_account =  'Cash - _TC'
+		settings.creation_user = 'Administrator'
+		settings.flags.ignore_permissions = True
+		settings.save()
+
+	def test_payment_entry_for_donations(self):
+		donor = create_donor()
+		create_mode_of_payment()
+		payment = frappe._dict({
+			'amount': 100,
+			'method': 'Debit Card',
+			'id': 'pay_MeXAmsgeKOhq7O'
+		})
+		donation = create_donation(donor, payment)
+
+		self.assertTrue(donation.name)
+
+		# Naive test to check if at all payment entry is generated
+		# This method is actually triggered from Payment Gateway
+		# In any case if details were missing, this would throw an error
+		donation.on_payment_authorized()
+		donation.reload()
+
+		self.assertEquals(donation.paid, 1)
+		self.assertTrue(frappe.db.exists('Payment Entry', {'reference_no': donation.name}))
+
+
+def create_donor_type():
+	if not frappe.db.exists('Donor Type', '_Test Donor'):
+		frappe.get_doc({
+			'doctype': 'Donor Type',
+			'donor_type': '_Test Donor'
+		}).insert()
+
+
+def create_donor():
+	donor = frappe.db.exists('Donor', 'donor@test.com')
+	if donor:
+		return frappe.get_doc('Donor', 'donor@test.com')
+	else:
+		return frappe.get_doc({
+			'doctype': 'Donor',
+			'donor_name': '_Test Donor',
+			'donor_type': '_Test Donor',
+			'email': 'donor@test.com'
+		}).insert()
+
+
+def create_mode_of_payment():
+	if not frappe.db.exists('Mode of Payment', 'Debit Card'):
+		frappe.get_doc({
+			'doctype': 'Mode of Payment',
+			'mode_of_payment': 'Debit Card',
+			'accounts': [{
+				'company': '_Test Company',
+				'default_account': 'Cash - _TC'
+			}]
+		}).insert()
\ No newline at end of file
diff --git a/erpnext/non_profit/doctype/donor/donor.json b/erpnext/non_profit/doctype/donor/donor.json
index 9639265..72f24ef 100644
--- a/erpnext/non_profit/doctype/donor/donor.json
+++ b/erpnext/non_profit/doctype/donor/donor.json
@@ -76,8 +76,13 @@
   }
  ],
  "image_field": "image",
- "links": [],
- "modified": "2020-09-16 23:46:04.083274",
+ "links": [
+  {
+   "link_doctype": "Donation",
+   "link_fieldname": "donor"
+  }
+ ],
+ "modified": "2021-02-17 16:36:33.470731",
  "modified_by": "Administrator",
  "module": "Non Profit",
  "name": "Donor",
diff --git a/erpnext/non_profit/doctype/donor/donor.py b/erpnext/non_profit/doctype/donor/donor.py
index 9121d0c..fb70e59 100644
--- a/erpnext/non_profit/doctype/donor/donor.py
+++ b/erpnext/non_profit/doctype/donor/donor.py
@@ -11,3 +11,8 @@
 		"""Load address and contacts in `__onload`"""
 		load_address_and_contact(self)
 
+	def validate(self):
+		from frappe.utils import validate_email_address
+		if self.email:
+			validate_email_address(self.email.strip(), True)
+
diff --git a/erpnext/non_profit/doctype/member/member.js b/erpnext/non_profit/doctype/member/member.js
index 199dcfc..6b8f1b1 100644
--- a/erpnext/non_profit/doctype/member/member.js
+++ b/erpnext/non_profit/doctype/member/member.js
@@ -3,7 +3,7 @@
 
 frappe.ui.form.on('Member', {
 	setup: function(frm) {
-		frappe.db.get_single_value("Membership Settings", "enable_razorpay").then(val => {
+		frappe.db.get_single_value('Non Profit Settings', 'enable_razorpay_for_memberships').then(val => {
 			if (val && (frm.doc.subscription_id || frm.doc.customer_id)) {
 				frm.set_df_property('razorpay_details_section', 'hidden', false);
 			}
diff --git a/erpnext/non_profit/doctype/member/member.py b/erpnext/non_profit/doctype/member/member.py
index 04b99f9..3ba2ee7 100644
--- a/erpnext/non_profit/doctype/member/member.py
+++ b/erpnext/non_profit/doctype/member/member.py
@@ -7,7 +7,7 @@
 from frappe import _
 from frappe.model.document import Document
 from frappe.contacts.address_and_contact import load_address_and_contact
-from frappe.utils import cint
+from frappe.utils import cint, get_link_to_form
 from frappe.integrations.utils import get_payment_gateway_controller
 from erpnext.non_profit.doctype.membership_type.membership_type import get_membership_type
 
@@ -26,9 +26,10 @@
 		validate_email_address(email.strip(), True)
 
 	def setup_subscription(self):
-		membership_settings = frappe.get_doc("Membership Settings")
-		if not membership_settings.enable_razorpay:
-			frappe.throw("Please enable Razorpay to setup subscription")
+		non_profit_settings = frappe.get_doc('Non Profit Settings')
+		if not non_profit_settings.enable_razorpay_for_memberships:
+			frappe.throw('Please check Enable Razorpay for Memberships in {0} to setup subscription').format(
+				get_link_to_form('Non Profit Settings', 'Non Profit Settings'))
 
 		controller = get_payment_gateway_controller("Razorpay")
 		settings = controller.get_settings({})
@@ -40,7 +41,7 @@
 
 		subscription_details = {
 			"plan_id": plan_id,
-			"billing_frequency": cint(membership_settings.billing_frequency),
+			"billing_frequency": cint(non_profit_settings.billing_frequency),
 			"customer_notify": 1
 		}
 
diff --git a/erpnext/non_profit/doctype/membership/membership.js b/erpnext/non_profit/doctype/membership/membership.js
index 573ac33..3187204 100644
--- a/erpnext/non_profit/doctype/membership/membership.js
+++ b/erpnext/non_profit/doctype/membership/membership.js
@@ -3,7 +3,7 @@
 
 frappe.ui.form.on('Membership', {
 	setup: function(frm) {
-		frappe.db.get_single_value("Membership Settings", "enable_razorpay").then(val => {
+		frappe.db.get_single_value("Non Profit Settings", "enable_razorpay_for_memberships").then(val => {
 			if (val) frm.set_df_property("razorpay_details_section", "hidden", false);
 		})
 	},
@@ -26,7 +26,7 @@
 			});
 		});
 
-		frappe.db.get_single_value("Membership Settings", "send_email").then(val => {
+		frappe.db.get_single_value("Non Profit Settings", "send_email").then(val => {
 			if (val) frm.add_custom_button("Send Acknowledgement", () => {
 				frm.call("send_acknowlement").then(() => {
 					frm.reload_doc();
diff --git a/erpnext/non_profit/doctype/membership/membership.json b/erpnext/non_profit/doctype/membership/membership.json
index 6da053f..11d32f9 100644
--- a/erpnext/non_profit/doctype/membership/membership.json
+++ b/erpnext/non_profit/doctype/membership/membership.json
@@ -10,6 +10,7 @@
   "member_name",
   "membership_type",
   "column_break_3",
+  "company",
   "membership_status",
   "membership_validity_section",
   "from_date",
@@ -132,11 +133,18 @@
    "fieldtype": "Data",
    "label": "Member Name",
    "read_only": 1
+  },
+  {
+   "fieldname": "company",
+   "fieldtype": "Link",
+   "label": "Company",
+   "options": "Company",
+   "reqd": 1
   }
  ],
  "index_web_pages_for_search": 1,
  "links": [],
- "modified": "2021-01-21 16:31:20.032656",
+ "modified": "2021-02-19 14:33:44.925122",
  "modified_by": "Administrator",
  "module": "Non Profit",
  "name": "Membership",
diff --git a/erpnext/non_profit/doctype/membership/membership.py b/erpnext/non_profit/doctype/membership/membership.py
index c113b80..191281f 100644
--- a/erpnext/non_profit/doctype/membership/membership.py
+++ b/erpnext/non_profit/doctype/membership/membership.py
@@ -6,6 +6,7 @@
 import json
 import frappe
 import six
+import os
 from datetime import datetime
 from frappe.model.document import Document
 from frappe.email import sendmail_to_system_managers
@@ -58,7 +59,7 @@
 		else:
 			self.from_date = nowdate()
 
-		if frappe.db.get_single_value("Membership Settings", "billing_cycle") == "Yearly":
+		if frappe.db.get_single_value("Non Profit Settings", "billing_cycle") == "Yearly":
 			self.to_date = add_years(self.from_date, 1)
 		else:
 			self.to_date = add_months(self.from_date, 1)
@@ -68,9 +69,9 @@
 			return
 		self.load_from_db()
 		self.db_set("paid", 1)
-		settings = frappe.get_doc("Membership Settings")
-		if settings.enable_invoicing and settings.create_for_web_forms:
-			self.generate_invoice(with_payment_entry=settings.make_payment_entry, save=True)
+		settings = frappe.get_doc("Non Profit Settings")
+		if settings.allow_invoicing and settings.automate_membership_invoicing:
+			self.generate_invoice(with_payment_entry=settings.automate_membership_payment_entries, save=True)
 
 
 	def generate_invoice(self, save=True, with_payment_entry=False):
@@ -85,7 +86,7 @@
 			frappe.throw(_("No customer linked to member {0}").format(frappe.bold(self.member)))
 
 		plan = frappe.get_doc("Membership Type", self.membership_type)
-		settings = frappe.get_doc("Membership Settings")
+		settings = frappe.get_doc("Non Profit Settings")
 		self.validate_membership_type_and_settings(plan, settings)
 
 		invoice = make_invoice(self, member, plan, settings)
@@ -102,7 +103,7 @@
 	def validate_membership_type_and_settings(self, plan, settings):
 		settings_link = get_link_to_form("Membership Type", self.membership_type)
 
-		if not settings.debit_account:
+		if not settings.membership_debit_account:
 			frappe.throw(_("You need to set <b>Debit Account</b> in {0}").format(settings_link))
 
 		if not settings.company:
@@ -113,25 +114,26 @@
 				get_link_to_form("Membership Type", self.membership_type)))
 
 	def make_payment_entry(self, settings, invoice):
-		if not settings.payment_account:
-			frappe.throw(_("You need to set <b>Payment Account</b> in {0}").format(
-				get_link_to_form("Membership Type", self.membership_type)))
+		if not settings.membership_payment_account:
+			frappe.throw(_("You need to set <b>Payment Account</b> for Membership in {0}").format(
+				get_link_to_form("Non Profit Settings", "Non Profit Settings")))
 
 		from erpnext.accounts.doctype.payment_entry.payment_entry import get_payment_entry
 		frappe.flags.ignore_account_permission = True
 		pe = get_payment_entry(dt="Sales Invoice", dn=invoice.name, bank_amount=invoice.grand_total)
 		frappe.flags.ignore_account_permission=False
-		pe.paid_to = settings.payment_account
+		pe.paid_to = settings.membership_payment_account
 		pe.reference_no = self.name
 		pe.reference_date = getdate()
-		pe.save(ignore_permissions=True)
+		pe.flags.ignore_mandatory = True
+		pe.save()
 		pe.submit()
 
 	def send_acknowlement(self):
-		settings = frappe.get_doc("Membership Settings")
+		settings = frappe.get_doc("Non Profit Settings")
 		if not settings.send_email:
 			frappe.throw(_("You need to enable <b>Send Acknowledge Email</b> in {0}").format(
-				get_link_to_form("Membership Settings", "Membership Settings")))
+				get_link_to_form("Non Profit Settings", "Non Profit Settings")))
 
 		member = frappe.get_doc("Member", self.member)
 		if not member.email_id:
@@ -170,7 +172,7 @@
 	invoice = frappe.get_doc({
 		"doctype": "Sales Invoice",
 		"customer": member.customer,
-		"debit_to": settings.debit_account,
+		"debit_to": settings.membership_debit_account,
 		"currency": membership.currency,
 		"company": settings.company,
 		"is_pos": 0,
@@ -183,7 +185,7 @@
 		]
 	})
 	invoice.set_missing_values()
-	invoice.insert(ignore_permissions=True)
+	invoice.insert()
 	invoice.submit()
 
 	frappe.msgprint(_("Sales Invoice created successfully"))
@@ -203,17 +205,18 @@
 		return None
 
 
-def verify_signature(data):
-	if frappe.flags.in_test:
+def verify_signature(data, endpoint="Membership"):
+	if frappe.flags.in_test or os.environ.get("CI"):
 		return True
 	signature = frappe.request.headers.get("X-Razorpay-Signature")
 
-	settings = frappe.get_doc("Membership Settings")
-	key = settings.get_webhook_secret()
+	settings = frappe.get_doc("Non Profit Settings")
+	key = settings.get_webhook_secret(endpoint)
 
 	controller = frappe.get_doc("Razorpay Settings")
 
 	controller.verify_signature(data, signature, key)
+	frappe.set_user(settings.creation_user)
 
 
 @frappe.whitelist(allow_guest=True)
@@ -222,7 +225,7 @@
 	try:
 		verify_signature(data)
 	except Exception as e:
-		log = frappe.log_error(e, "Webhook Verification Error")
+		log = frappe.log_error(e, "Membership Webhook Verification Error")
 		notify_failure(log)
 		return { "status": "Failed", "reason": e}
 
@@ -250,16 +253,15 @@
 
 			member.subscription_id = subscription.id
 			member.customer_id = payment.customer_id
-			if subscription.notes and type(subscription.notes) == dict:
-				notes = "\n".join("{}: {}".format(k, v) for k, v in subscription.notes.items())
-				member.add_comment("Comment", notes)
-			elif subscription.notes and type(subscription.notes) == str:
-				member.add_comment("Comment", subscription.notes)
 
+			if subscription.get("notes"):
+				member = get_additional_notes(member, subscription)
 
+		company = get_company_for_memberships()
 		# Update Membership
 		membership = frappe.new_doc("Membership")
 		membership.update({
+			"company": company,
 			"member": member.name,
 			"membership_status": "Current",
 			"membership_type": member.membership_type,
@@ -270,13 +272,20 @@
 			"to_date": datetime.fromtimestamp(subscription.current_end),
 			"amount": payment.amount / 100 # Convert to rupees from paise
 		})
-		membership.insert(ignore_permissions=True)
+		membership.flags.ignore_mandatory = True
+		membership.insert()
 
 		# Update membership values
 		member.subscription_start = datetime.fromtimestamp(subscription.start_at)
 		member.subscription_end = datetime.fromtimestamp(subscription.end_at)
 		member.subscription_activated = 1
-		member.save(ignore_permissions=True)
+		member.flags.ignore_mandatory = True
+		member.save()
+
+		settings = frappe.get_doc("Non Profit Settings")
+		if settings.allow_invoicing and settings.automate_membership_invoicing:
+			membership.generate_invoice(with_payment_entry=settings.automate_membership_payment_entries, save=True)
+
 	except Exception as e:
 		message = "{0}\n\n{1}\n\n{2}: {3}".format(e, frappe.get_traceback(), __("Payment ID"), payment.id)
 		log = frappe.log_error(message, _("Error creating membership entry for {0}").format(member.name))
@@ -286,6 +295,39 @@
 	return { "status": "Success" }
 
 
+def get_company_for_memberships():
+	company = frappe.db.get_single_value("Non Profit Settings", "company")
+	if not company:
+		from erpnext.healthcare.setup import get_company
+		company = get_company()
+	return company
+
+
+def get_additional_notes(member, subscription):
+	if type(subscription.notes) == dict:
+		for k, v in subscription.notes.items():
+			notes = "\n".join("{}: {}".format(k, v))
+
+			# extract member name from notes
+			if "name" in k.lower():
+				member.update({
+					"member_name": subscription.notes.get(k)
+				})
+
+			# extract pan number from notes
+			if "pan" in k.lower():
+				member.update({
+					"pan_number": subscription.notes.get(k)
+				})
+
+		member.add_comment("Comment", notes)
+
+	elif type(subscription.notes) == str:
+		member.add_comment("Comment", subscription.notes)
+
+	return member
+
+
 def notify_failure(log):
 	try:
 		content = """
diff --git a/erpnext/non_profit/doctype/membership/test_membership.py b/erpnext/non_profit/doctype/membership/test_membership.py
index ff7e6c4..31da792 100644
--- a/erpnext/non_profit/doctype/membership/test_membership.py
+++ b/erpnext/non_profit/doctype/membership/test_membership.py
@@ -10,33 +10,7 @@
 
 class TestMembership(unittest.TestCase):
 	def setUp(self):
-		# Get default company
-		company = frappe.get_doc("Company", erpnext.get_default_company())
-
-		# update membership settings
-		settings = frappe.get_doc("Membership Settings")
-		# Enable razorpay
-		settings.enable_razorpay = 1
-		settings.billing_cycle = "Monthly"
-		settings.billing_frequency = 24
-		# Enable invoicing
-		settings.enable_invoicing = 1
-		settings.make_payment_entry = 1
-		settings.company = company.name
-		settings.payment_account = company.default_cash_account
-		settings.debit_account = company.default_receivable_account
-		settings.save()
-
-		# make test plan
-		if not frappe.db.exists("Membership Type", "_rzpy_test_milythm"):
-			plan = frappe.new_doc("Membership Type")
-			plan.membership_type = "_rzpy_test_milythm"
-			plan.amount = 100
-			plan.razorpay_plan_id = "_rzpy_test_milythm"
-			plan.linked_item = create_item("_Test Item for Non Profit Membership").name
-			plan.insert()
-		else:
-			plan = frappe.get_doc("Membership Type", "_rzpy_test_milythm")
+		plan = setup_membership()
 
 		# make test member
 		self.member_doc = create_member(frappe._dict({
@@ -78,7 +52,7 @@
 		})
 
 def set_config(key, value):
-	frappe.db.set_value("Membership Settings", None, key, value)
+	frappe.db.set_value("Non Profit Settings", None, key, value)
 
 def make_membership(member, payload={}):
 	data = {
@@ -109,3 +83,36 @@
 	else:
 		item = frappe.get_doc("Item", item_code)
 	return item
+
+def setup_membership():
+	# Get default company
+	company = frappe.get_doc("Company", erpnext.get_default_company())
+
+	# update non profit settings
+	settings = frappe.get_doc("Non Profit Settings")
+	# Enable razorpay
+	settings.enable_razorpay_for_memberships = 1
+	settings.billing_cycle = "Monthly"
+	settings.billing_frequency = 24
+	# Enable invoicing
+	settings.allow_invoicing = 1
+	settings.automate_membership_payment_entries = 1
+	settings.company = company.name
+	settings.donation_company = company.name
+	settings.membership_payment_account = company.default_cash_account
+	settings.membership_debit_account = company.default_receivable_account
+	settings.flags.ignore_mandatory = True
+	settings.save()
+
+	# make test plan
+	if not frappe.db.exists("Membership Type", "_rzpy_test_milythm"):
+		plan = frappe.new_doc("Membership Type")
+		plan.membership_type = "_rzpy_test_milythm"
+		plan.amount = 100
+		plan.razorpay_plan_id = "_rzpy_test_milythm"
+		plan.linked_item = create_item("_Test Item for Non Profit Membership").name
+		plan.insert()
+	else:
+		plan = frappe.get_doc("Membership Type", "_rzpy_test_milythm")
+
+	return plan
\ No newline at end of file
diff --git a/erpnext/non_profit/doctype/membership_settings/membership_settings.js b/erpnext/non_profit/doctype/membership_settings/membership_settings.js
deleted file mode 100644
index c95aab2..0000000
--- a/erpnext/non_profit/doctype/membership_settings/membership_settings.js
+++ /dev/null
@@ -1,81 +0,0 @@
-// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
-// For license information, please see license.txt
-
-frappe.ui.form.on("Membership Settings", {
-	refresh: function(frm) {
-		if (frm.doc.webhook_secret) {
-			frm.add_custom_button(__("Revoke <Key></Key>"), () => {
-				frm.call("revoke_key").then(() => {
-					frm.refresh();
-				})
-			});
-		}
-
-		frm.set_query("inv_print_format", function() {
-			return {
-				filters: {
-					"doc_type": "Sales Invoice"
-				}
-			};
-		});
-
-		frm.set_query("membership_print_format", function() {
-			return {
-				filters: {
-					"doc_type": "Membership"
-				}
-			};
-		});
-
-		frm.set_query("debit_account", function() {
-			return {
-				filters: {
-					"account_type": "Receivable",
-					"is_group": 0,
-					"company": frm.doc.company
-				}
-			};
-		});
-
-		frm.set_query("payment_account", function () {
-			var account_types = ["Bank", "Cash"];
-			return {
-				filters: {
-					"account_type": ["in", account_types],
-					"is_group": 0,
-					"company": frm.doc.company
-				}
-			};
-		});
-
-		let docs_url = "https://docs.erpnext.com/docs/user/manual/en/non_profit/membership";
-
-		frm.set_intro(__("You can learn more about memberships in the manual. ") + `<a href='${docs_url}'>${__('ERPNext Docs')}</a>`, true);
-
-		frm.trigger("add_generate_button");
-		frm.trigger("add_copy_buttonn");
-	},
-
-	add_generate_button: function(frm) {
-		let label;
-
-		if (frm.doc.webhook_secret) {
-			label = __("Regenerate Webhook Secret");
-		} else {
-			label = __("Generate Webhook Secret");
-		}
-		frm.add_custom_button(label, () => {
-			frm.call("generate_webhook_key").then(() => {
-				frm.refresh();
-			});
-		});
-	},
-
-	add_copy_buttonn: function(frm) {
-		if (frm.doc.webhook_secret) {
-			frm.add_custom_button(__("Copy Webhook URL"), () => {
-				frappe.utils.copy_to_clipboard(`https://${frappe.boot.sitename}/api/method/erpnext.non_profit.doctype.membership.membership.trigger_razorpay_subscription`);
-			});
-		}
-	}
-});
diff --git a/erpnext/non_profit/doctype/membership_settings/membership_settings.json b/erpnext/non_profit/doctype/membership_settings/membership_settings.json
deleted file mode 100644
index 3887b0a..0000000
--- a/erpnext/non_profit/doctype/membership_settings/membership_settings.json
+++ /dev/null
@@ -1,192 +0,0 @@
-{
- "actions": [],
- "creation": "2020-03-29 12:57:03.005120",
- "doctype": "DocType",
- "editable_grid": 1,
- "engine": "InnoDB",
- "field_order": [
-  "enable_razorpay",
-  "razorpay_settings_section",
-  "billing_cycle",
-  "billing_frequency",
-  "webhook_secret",
-  "column_break_6",
-  "enable_invoicing",
-  "create_for_web_forms",
-  "make_payment_entry",
-  "company",
-  "debit_account",
-  "payment_account",
-  "column_break_9",
-  "send_email",
-  "send_invoice",
-  "membership_print_format",
-  "inv_print_format",
-  "email_template"
- ],
- "fields": [
-  {
-   "fieldname": "billing_cycle",
-   "fieldtype": "Select",
-   "label": "Billing Cycle",
-   "options": "Monthly\nYearly"
-  },
-  {
-   "default": "0",
-   "fieldname": "enable_razorpay",
-   "fieldtype": "Check",
-   "label": "Enable RazorPay For Memberships"
-  },
-  {
-   "depends_on": "eval:doc.enable_razorpay",
-   "fieldname": "razorpay_settings_section",
-   "fieldtype": "Section Break",
-   "label": "RazorPay Settings"
-  },
-  {
-   "description": "The number of billing cycles for which the customer should be charged. For example, if a customer is buying a 1-year membership that should be billed on a monthly basis, this value should be 12.",
-   "fieldname": "billing_frequency",
-   "fieldtype": "Int",
-   "label": "Billing Frequency"
-  },
-  {
-   "fieldname": "webhook_secret",
-   "fieldtype": "Password",
-   "label": "Webhook Secret",
-   "read_only": 1
-  },
-  {
-   "fieldname": "column_break_6",
-   "fieldtype": "Section Break",
-   "label": "Invoicing"
-  },
-  {
-   "depends_on": "eval:doc.enable_invoicing",
-   "fieldname": "debit_account",
-   "fieldtype": "Link",
-   "label": "Debit Account",
-   "mandatory_depends_on": "eval:doc.enable_auto_invoicing",
-   "options": "Account"
-  },
-  {
-   "fieldname": "column_break_9",
-   "fieldtype": "Column Break"
-  },
-  {
-   "depends_on": "eval:doc.enable_invoicing",
-   "fieldname": "company",
-   "fieldtype": "Link",
-   "label": "Company",
-   "mandatory_depends_on": "eval:doc.enable_auto_invoicing",
-   "options": "Company"
-  },
-  {
-   "default": "0",
-   "depends_on": "eval:doc.enable_invoicing && doc.send_email",
-   "fieldname": "send_invoice",
-   "fieldtype": "Check",
-   "label": "Send Invoice with Email"
-  },
-  {
-   "default": "0",
-   "fieldname": "send_email",
-   "fieldtype": "Check",
-   "label": "Send Membership Acknowledgement"
-  },
-  {
-   "depends_on": "eval: doc.send_invoice",
-   "fieldname": "inv_print_format",
-   "fieldtype": "Link",
-   "label": "Invoice Print Format",
-   "mandatory_depends_on": "eval: doc.send_invoice",
-   "options": "Print Format"
-  },
-  {
-   "depends_on": "eval:doc.send_email",
-   "fieldname": "membership_print_format",
-   "fieldtype": "Link",
-   "label": "Membership Print Format",
-   "options": "Print Format"
-  },
-  {
-   "depends_on": "eval:doc.send_email",
-   "fieldname": "email_template",
-   "fieldtype": "Link",
-   "label": "Email Template",
-   "mandatory_depends_on": "eval:doc.send_email",
-   "options": "Email Template"
-  },
-  {
-   "default": "0",
-   "fieldname": "enable_invoicing",
-   "fieldtype": "Check",
-   "label": "Enable Invoicing",
-   "mandatory_depends_on": "eval:doc.send_invoice || doc.make_payment_entry"
-  },
-  {
-   "default": "0",
-   "depends_on": "eval:doc.enable_invoicing",
-   "description": "Auto creates Payment Entry for Sales Invoices created for Membership from web forms.",
-   "fieldname": "make_payment_entry",
-   "fieldtype": "Check",
-   "label": "Make Payment Entry"
-  },
-  {
-   "depends_on": "eval:doc.make_payment_entry",
-   "fieldname": "payment_account",
-   "fieldtype": "Link",
-   "label": "Payment To",
-   "mandatory_depends_on": "eval:doc.make_payment_entry",
-   "options": "Account"
-  },
-  {
-   "default": "0",
-   "depends_on": "eval:doc.enable_invoicing",
-   "description": "Automatically create an invoice when payment is authorized from a web form entry",
-   "fieldname": "create_for_web_forms",
-   "fieldtype": "Check",
-   "label": "Auto Create Invoice for Web Forms"
-  }
- ],
- "index_web_pages_for_search": 1,
- "issingle": 1,
- "links": [],
- "modified": "2021-01-21 19:57:53.213286",
- "modified_by": "Administrator",
- "module": "Non Profit",
- "name": "Membership Settings",
- "owner": "Administrator",
- "permissions": [
-  {
-   "create": 1,
-   "delete": 1,
-   "email": 1,
-   "print": 1,
-   "read": 1,
-   "role": "System Manager",
-   "share": 1,
-   "write": 1
-  },
-  {
-   "create": 1,
-   "delete": 1,
-   "email": 1,
-   "print": 1,
-   "read": 1,
-   "role": "Non Profit Manager",
-   "share": 1,
-   "write": 1
-  },
-  {
-   "email": 1,
-   "print": 1,
-   "read": 1,
-   "role": "Non Profit Member",
-   "share": 1
-  }
- ],
- "quick_entry": 1,
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 1
-}
\ No newline at end of file
diff --git a/erpnext/non_profit/doctype/membership_settings/membership_settings.py b/erpnext/non_profit/doctype/membership_settings/membership_settings.py
deleted file mode 100644
index f3b2eee..0000000
--- a/erpnext/non_profit/doctype/membership_settings/membership_settings.py
+++ /dev/null
@@ -1,33 +0,0 @@
-# -*- coding: utf-8 -*-
-# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
-# For license information, please see license.txt
-
-from __future__ import unicode_literals
-import frappe
-from frappe import _
-from frappe.integrations.utils import get_payment_gateway_controller
-from frappe.model.document import Document
-
-class MembershipSettings(Document):
-	def generate_webhook_key(self):
-		key = frappe.generate_hash(length=20)
-		self.webhook_secret = key
-		self.save()
-
-		frappe.msgprint(
-			_("Here is your webhook secret, this will be shown to you only once.") + "<br><br>" + key,
-			_("Webhook Secret")
-		);
-
-	def revoke_key(self):
-		self.webhook_secret = None;
-		self.save()
-
-	def get_webhook_secret(self):
-		return self.get_password(fieldname="webhook_secret", raise_exception=False)
-
-@frappe.whitelist()
-def get_plans_for_membership(*args, **kwargs):
-	controller = get_payment_gateway_controller("Razorpay")
-	plans = controller.get_plans()
-	return [plan.get("item") for plan in plans.get("items")]
\ No newline at end of file
diff --git a/erpnext/non_profit/doctype/membership_type/membership_type.js b/erpnext/non_profit/doctype/membership_type/membership_type.js
index 91a5cb7..2f24276 100644
--- a/erpnext/non_profit/doctype/membership_type/membership_type.js
+++ b/erpnext/non_profit/doctype/membership_type/membership_type.js
@@ -3,11 +3,11 @@
 
 frappe.ui.form.on('Membership Type', {
 	refresh: function (frm) {
-		frappe.db.get_single_value('Membership Settings', 'enable_razorpay').then(val => {
+		frappe.db.get_single_value('Non Profit Settings', 'enable_razorpay_for_memberships').then(val => {
 			if (val) frm.set_df_property('razorpay_plan_id', 'hidden', false);
 		});
 
-		frappe.db.get_single_value('Membership Settings', 'enable_invoicing').then(val => {
+		frappe.db.get_single_value('Non Profit Settings', 'allow_invoicing').then(val => {
 			if (val) frm.set_df_property('linked_item', 'hidden', false);
 		});
 
diff --git a/erpnext/non_profit/doctype/membership_settings/__init__.py b/erpnext/non_profit/doctype/non_profit_settings/__init__.py
similarity index 100%
rename from erpnext/non_profit/doctype/membership_settings/__init__.py
rename to erpnext/non_profit/doctype/non_profit_settings/__init__.py
diff --git a/erpnext/non_profit/doctype/non_profit_settings/non_profit_settings.js b/erpnext/non_profit/doctype/non_profit_settings/non_profit_settings.js
new file mode 100644
index 0000000..cff92b4
--- /dev/null
+++ b/erpnext/non_profit/doctype/non_profit_settings/non_profit_settings.js
@@ -0,0 +1,112 @@
+// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+frappe.ui.form.on("Non Profit Settings", {
+	refresh: function(frm) {
+		frm.set_query("inv_print_format", function() {
+			return {
+				filters: {
+					"doc_type": "Sales Invoice"
+				}
+			};
+		});
+
+		frm.set_query("membership_print_format", function() {
+			return {
+				filters: {
+					"doc_type": "Membership"
+				}
+			};
+		});
+
+		frm.set_query("debit_account", function() {
+			return {
+				filters: {
+					"account_type": "Receivable",
+					"is_group": 0,
+					"company": frm.doc.company
+				}
+			};
+		});
+
+		frm.set_query("membership_payment_account", function () {
+			var account_types = ["Bank", "Cash"];
+			return {
+				filters: {
+					"account_type": ["in", account_types],
+					"is_group": 0,
+					"company": frm.doc.company
+				}
+			};
+		});
+
+		let docs_url = "https://docs.erpnext.com/docs/user/manual/en/non_profit/membership";
+
+		frm.set_intro(__("You can learn more about memberships in the manual. ") + `<a href='${docs_url}'>${__('ERPNext Docs')}</a>`, true);
+		frm.trigger("setup_buttons_for_membership");
+		frm.trigger("setup_buttons_for_donation");
+	},
+
+	setup_buttons_for_membership: function(frm) {
+		let label;
+
+		if (frm.doc.membership_webhook_secret) {
+
+			frm.add_custom_button(__("Copy Webhook URL"), () => {
+				frappe.utils.copy_to_clipboard(`https://${frappe.boot.sitename}/api/method/erpnext.non_profit.doctype.membership.membership.trigger_razorpay_subscription`);
+			}, __("Memberships"));
+
+			frm.add_custom_button(__("Revoke Key"), () => {
+				frm.call("revoke_key",  {
+					key: "membership_webhook_secret"
+				}).then(() => {
+					frm.refresh();
+				});
+			}, __("Memberships"));
+
+			label = __("Regenerate Webhook Secret");
+
+		} else {
+			label = __("Generate Webhook Secret");
+		}
+
+		frm.add_custom_button(label, () => {
+			frm.call("generate_webhook_secret", {
+				field: "membership_webhook_secret"
+			}).then(() => {
+				frm.refresh();
+			});
+		}, __("Memberships"));
+	},
+
+	setup_buttons_for_donation: function(frm) {
+		let label;
+
+		if (frm.doc.donation_webhook_secret) {
+			label = __("Regenerate Webhook Secret");
+
+			frm.add_custom_button(__("Copy Webhook URL"), () => {
+				frappe.utils.copy_to_clipboard(`https://${frappe.boot.sitename}/api/method/erpnext.non_profit.doctype.donation.donation.capture_razorpay_donations`);
+			}, __("Donations"));
+
+			frm.add_custom_button(__("Revoke Key"), () => {
+				frm.call("revoke_key", {
+					key: "donation_webhook_secret"
+				}).then(() => {
+					frm.refresh();
+				});
+			}, __("Donations"));
+
+		} else {
+			label = __("Generate Webhook Secret");
+		}
+
+		frm.add_custom_button(label, () => {
+			frm.call("generate_webhook_secret", {
+				field: "donation_webhook_secret"
+			}).then(() => {
+				frm.refresh();
+			});
+		}, __("Donations"));
+	}
+});
diff --git a/erpnext/non_profit/doctype/non_profit_settings/non_profit_settings.json b/erpnext/non_profit/doctype/non_profit_settings/non_profit_settings.json
new file mode 100644
index 0000000..25ff0c1
--- /dev/null
+++ b/erpnext/non_profit/doctype/non_profit_settings/non_profit_settings.json
@@ -0,0 +1,273 @@
+{
+ "actions": [],
+ "creation": "2020-03-29 12:57:03.005120",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "enable_razorpay_for_memberships",
+  "razorpay_settings_section",
+  "billing_cycle",
+  "billing_frequency",
+  "membership_webhook_secret",
+  "column_break_6",
+  "allow_invoicing",
+  "automate_membership_invoicing",
+  "automate_membership_payment_entries",
+  "company",
+  "membership_debit_account",
+  "membership_payment_account",
+  "column_break_9",
+  "send_email",
+  "send_invoice",
+  "membership_print_format",
+  "inv_print_format",
+  "email_template",
+  "donation_settings_section",
+  "donation_company",
+  "default_donor_type",
+  "donation_webhook_secret",
+  "column_break_22",
+  "automate_donation_payment_entries",
+  "donation_debit_account",
+  "donation_payment_account",
+  "section_break_27",
+  "creation_user"
+ ],
+ "fields": [
+  {
+   "fieldname": "billing_cycle",
+   "fieldtype": "Select",
+   "label": "Billing Cycle",
+   "options": "Monthly\nYearly"
+  },
+  {
+   "depends_on": "eval:doc.enable_razorpay_for_memberships",
+   "fieldname": "razorpay_settings_section",
+   "fieldtype": "Section Break",
+   "label": "RazorPay Settings for Memberships"
+  },
+  {
+   "description": "The number of billing cycles for which the customer should be charged. For example, if a customer is buying a 1-year membership that should be billed on a monthly basis, this value should be 12.",
+   "fieldname": "billing_frequency",
+   "fieldtype": "Int",
+   "label": "Billing Frequency"
+  },
+  {
+   "fieldname": "column_break_6",
+   "fieldtype": "Section Break",
+   "label": "Membership Invoicing"
+  },
+  {
+   "fieldname": "column_break_9",
+   "fieldtype": "Column Break"
+  },
+  {
+   "description": "This company will be set for the Memberships created via webhook.",
+   "fieldname": "company",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "label": "Company",
+   "options": "Company",
+   "reqd": 1
+  },
+  {
+   "default": "0",
+   "depends_on": "eval:doc.allow_invoicing && doc.send_email",
+   "fieldname": "send_invoice",
+   "fieldtype": "Check",
+   "label": "Send Invoice with Email"
+  },
+  {
+   "default": "0",
+   "fieldname": "send_email",
+   "fieldtype": "Check",
+   "label": "Send Membership Acknowledgement"
+  },
+  {
+   "depends_on": "eval: doc.send_invoice",
+   "fieldname": "inv_print_format",
+   "fieldtype": "Link",
+   "label": "Invoice Print Format",
+   "mandatory_depends_on": "eval: doc.send_invoice",
+   "options": "Print Format"
+  },
+  {
+   "depends_on": "eval:doc.send_email",
+   "fieldname": "membership_print_format",
+   "fieldtype": "Link",
+   "label": "Membership Print Format",
+   "options": "Print Format"
+  },
+  {
+   "depends_on": "eval:doc.send_email",
+   "fieldname": "email_template",
+   "fieldtype": "Link",
+   "label": "Email Template",
+   "mandatory_depends_on": "eval:doc.send_email",
+   "options": "Email Template"
+  },
+  {
+   "default": "0",
+   "fieldname": "allow_invoicing",
+   "fieldtype": "Check",
+   "label": "Allow Invoicing for Memberships",
+   "mandatory_depends_on": "eval:doc.send_invoice || doc.make_payment_entry"
+  },
+  {
+   "default": "0",
+   "depends_on": "eval:doc.allow_invoicing",
+   "description": "Automatically create an invoice when payment is authorized from a web form entry",
+   "fieldname": "automate_membership_invoicing",
+   "fieldtype": "Check",
+   "label": "Automate Invoicing for Web Forms"
+  },
+  {
+   "default": "0",
+   "depends_on": "eval:doc.allow_invoicing",
+   "description": "Auto creates Payment Entry for Sales Invoices created for Membership from web forms.",
+   "fieldname": "automate_membership_payment_entries",
+   "fieldtype": "Check",
+   "label": "Automate Payment Entry Creation"
+  },
+  {
+   "default": "0",
+   "fieldname": "enable_razorpay_for_memberships",
+   "fieldtype": "Check",
+   "label": "Enable RazorPay For Memberships"
+  },
+  {
+   "depends_on": "eval:doc.automate_membership_payment_entries",
+   "description": "Account for accepting membership payments",
+   "fieldname": "membership_payment_account",
+   "fieldtype": "Link",
+   "label": "Membership Payment To",
+   "mandatory_depends_on": "eval:doc.automate_membership_payment_entries",
+   "options": "Account"
+  },
+  {
+   "fieldname": "membership_webhook_secret",
+   "fieldtype": "Password",
+   "label": "Membership Webhook Secret",
+   "read_only": 1
+  },
+  {
+   "fieldname": "donation_webhook_secret",
+   "fieldtype": "Password",
+   "label": "Donation Webhook Secret",
+   "read_only": 1
+  },
+  {
+   "depends_on": "automate_donation_payment_entries",
+   "description": "Account for accepting donation payments",
+   "fieldname": "donation_payment_account",
+   "fieldtype": "Link",
+   "label": "Donation Payment To",
+   "mandatory_depends_on": "automate_donation_payment_entries",
+   "options": "Account"
+  },
+  {
+   "default": "0",
+   "description": "Auto creates Payment Entry for Donations created from web forms.",
+   "fieldname": "automate_donation_payment_entries",
+   "fieldtype": "Check",
+   "label": "Automate Donation Payment Entries"
+  },
+  {
+   "depends_on": "eval:doc.allow_invoicing",
+   "fieldname": "membership_debit_account",
+   "fieldtype": "Link",
+   "label": "Debit Account",
+   "mandatory_depends_on": "eval:doc.allow_invoicing",
+   "options": "Account"
+  },
+  {
+   "depends_on": "automate_donation_payment_entries",
+   "fieldname": "donation_debit_account",
+   "fieldtype": "Link",
+   "label": "Debit Account",
+   "mandatory_depends_on": "automate_donation_payment_entries",
+   "options": "Account"
+  },
+  {
+   "description": "This company will be set for the Donations created via webhook.",
+   "fieldname": "donation_company",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "label": "Company",
+   "options": "Company",
+   "reqd": 1
+  },
+  {
+   "fieldname": "donation_settings_section",
+   "fieldtype": "Section Break",
+   "label": "Donation Settings"
+  },
+  {
+   "fieldname": "column_break_22",
+   "fieldtype": "Column Break"
+  },
+  {
+   "description": "This Donor Type will be set for the Donor created via Donation web form entry.",
+   "fieldname": "default_donor_type",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "label": "Default Donor Type",
+   "options": "Donor Type",
+   "reqd": 1
+  },
+  {
+   "fieldname": "section_break_27",
+   "fieldtype": "Section Break"
+  },
+  {
+   "description": "The user that will be used to create Donations, Memberships, Invoices, and Payment Entries. This user should have the relevant permissions.",
+   "fieldname": "creation_user",
+   "fieldtype": "Link",
+   "label": "Creation User",
+   "options": "User",
+   "reqd": 1
+  }
+ ],
+ "index_web_pages_for_search": 1,
+ "issingle": 1,
+ "links": [],
+ "modified": "2021-03-11 10:43:38.124240",
+ "modified_by": "Administrator",
+ "module": "Non Profit",
+ "name": "Non Profit Settings",
+ "owner": "Administrator",
+ "permissions": [
+  {
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "print": 1,
+   "read": 1,
+   "role": "System Manager",
+   "share": 1,
+   "write": 1
+  },
+  {
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "print": 1,
+   "read": 1,
+   "role": "Non Profit Manager",
+   "share": 1,
+   "write": 1
+  },
+  {
+   "email": 1,
+   "print": 1,
+   "read": 1,
+   "role": "Non Profit Member",
+   "share": 1
+  }
+ ],
+ "quick_entry": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/non_profit/doctype/non_profit_settings/non_profit_settings.py b/erpnext/non_profit/doctype/non_profit_settings/non_profit_settings.py
new file mode 100644
index 0000000..108554c
--- /dev/null
+++ b/erpnext/non_profit/doctype/non_profit_settings/non_profit_settings.py
@@ -0,0 +1,36 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe import _
+from frappe.integrations.utils import get_payment_gateway_controller
+from frappe.model.document import Document
+
+class NonProfitSettings(Document):
+	def generate_webhook_secret(self, field="membership_webhook_secret"):
+		key = frappe.generate_hash(length=20)
+		self.set(field, key)
+		self.save()
+
+		secret_for = "Membership" if field == "membership_webhook_secret" else "Donation"
+
+		frappe.msgprint(
+			_("Here is your webhook secret for {0} API, this will be shown to you only once.").format(secret_for) + "<br><br>" + key,
+			_("Webhook Secret")
+		)
+
+	def revoke_key(self, key):
+		self.set(key, None)
+		self.save()
+
+	def get_webhook_secret(self, endpoint="Membership"):
+		fieldname = "membership_webhook_secret" if endpoint == "Membership" else "donation_webhook_secret"
+		return self.get_password(fieldname=fieldname, raise_exception=False)
+
+@frappe.whitelist()
+def get_plans_for_membership(*args, **kwargs):
+	controller = get_payment_gateway_controller("Razorpay")
+	plans = controller.get_plans()
+	return [plan.get("item") for plan in plans.get("items")]
\ No newline at end of file
diff --git a/erpnext/non_profit/doctype/membership_settings/test_membership_settings.py b/erpnext/non_profit/doctype/non_profit_settings/test_non_profit_settings.py
similarity index 79%
rename from erpnext/non_profit/doctype/membership_settings/test_membership_settings.py
rename to erpnext/non_profit/doctype/non_profit_settings/test_non_profit_settings.py
index 2ad7984..3f0ede3 100644
--- a/erpnext/non_profit/doctype/membership_settings/test_membership_settings.py
+++ b/erpnext/non_profit/doctype/non_profit_settings/test_non_profit_settings.py
@@ -6,5 +6,5 @@
 # import frappe
 import unittest
 
-class TestMembershipSettings(unittest.TestCase):
+class TestNonProfitSettings(unittest.TestCase):
 	pass
diff --git a/erpnext/non_profit/workspace/non_profit/non_profit.json b/erpnext/non_profit/workspace/non_profit/non_profit.json
index da2a514..2557d77 100644
--- a/erpnext/non_profit/workspace/non_profit/non_profit.json
+++ b/erpnext/non_profit/workspace/non_profit/non_profit.json
@@ -10,6 +10,7 @@
  "hide_custom": 0,
  "icon": "non-profit",
  "idx": 0,
+ "is_default": 0,
  "is_standard": 1,
  "label": "Non Profit",
  "links": [
@@ -109,7 +110,7 @@
    "hidden": 0,
    "is_query_report": 0,
    "label": "Membership Settings",
-   "link_to": "Membership Settings",
+   "link_to": "Non Profit Settings",
    "link_type": "DocType",
    "onboard": 0,
    "type": "Link"
@@ -161,7 +162,7 @@
   {
    "hidden": 0,
    "is_query_report": 0,
-   "label": "Donor",
+   "label": "Donation",
    "onboard": 0,
    "type": "Card Break"
   },
@@ -184,9 +185,35 @@
    "link_type": "DocType",
    "onboard": 0,
    "type": "Link"
+  },
+  {
+   "hidden": 0,
+   "is_query_report": 0,
+   "label": "Donation",
+   "link_to": "Donation",
+   "link_type": "DocType",
+   "onboard": 0,
+   "type": "Link"
+  },
+  {
+   "hidden": 0,
+   "is_query_report": 0,
+   "label": "Tax Exemption Certification (India)",
+   "link_type": "DocType",
+   "onboard": 0,
+   "type": "Card Break"
+  },
+  {
+   "hidden": 0,
+   "is_query_report": 0,
+   "label": "Tax Exemption 80G Certificate",
+   "link_to": "Tax Exemption 80G Certificate",
+   "link_type": "DocType",
+   "onboard": 0,
+   "type": "Link"
   }
  ],
- "modified": "2020-12-01 13:38:38.351409",
+ "modified": "2021-03-11 11:38:09.140655",
  "modified_by": "Administrator",
  "module": "Non Profit",
  "name": "Non Profit",
@@ -201,8 +228,8 @@
    "type": "DocType"
   },
   {
-   "label": "Membership Settings",
-   "link_to": "Membership Settings",
+   "label": "Non Profit Settings",
+   "link_to": "Non Profit Settings",
    "type": "DocType"
   },
   {
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index ba31fee..59b12f3 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -756,3 +756,6 @@
 erpnext.patches.v13_0.item_reposting_for_incorrect_sl_and_gl
 erpnext.patches.v13_0.delete_old_bank_reconciliation_doctypes
 erpnext.patches.v13_0.update_vehicle_no_reqd_condition
+erpnext.patches.v13_0.setup_fields_for_80g_certificate_and_donation
+erpnext.patches.v13_0.rename_membership_settings_to_non_profit_settings
+erpnext.patches.v13_0.setup_gratuity_rule_for_india_and_uae
diff --git a/erpnext/patches/v13_0/rename_membership_settings_to_non_profit_settings.py b/erpnext/patches/v13_0/rename_membership_settings_to_non_profit_settings.py
new file mode 100644
index 0000000..3fa09a7
--- /dev/null
+++ b/erpnext/patches/v13_0/rename_membership_settings_to_non_profit_settings.py
@@ -0,0 +1,22 @@
+from __future__ import unicode_literals
+import frappe
+from frappe.model.utils.rename_field import rename_field
+
+def execute():
+	if frappe.db.table_exists("Membership Settings"):
+		frappe.rename_doc("DocType", "Membership Settings", "Non Profit Settings")
+		frappe.reload_doctype("Non Profit Settings", force=True)
+
+	if frappe.db.table_exists("Non Profit Settings"):
+		rename_fields_map = {
+			"enable_invoicing": "allow_invoicing",
+			"create_for_web_forms": "automate_membership_invoicing",
+			"make_payment_entry": "automate_membership_payment_entries",
+			"enable_razorpay": "enable_razorpay_for_memberships",
+			"debit_account": "membership_debit_account",
+			"payment_account": "membership_payment_account",
+			"webhook_secret": "membership_webhook_secret"
+		}
+
+		for old_name, new_name in rename_fields_map.items():
+			rename_field("Non Profit Settings", old_name, new_name)
\ No newline at end of file
diff --git a/erpnext/patches/v13_0/setup_fields_for_80g_certificate_and_donation.py b/erpnext/patches/v13_0/setup_fields_for_80g_certificate_and_donation.py
new file mode 100644
index 0000000..aea53f8
--- /dev/null
+++ b/erpnext/patches/v13_0/setup_fields_for_80g_certificate_and_donation.py
@@ -0,0 +1,16 @@
+import frappe
+from erpnext.regional.india.setup import make_custom_fields
+
+def execute():
+	company = frappe.get_all('Company', filters = {'country': 'India'})
+	if not company:
+		return
+
+	make_custom_fields()
+
+	if not frappe.db.exists('Party Type', 'Donor'):
+		frappe.get_doc({
+			'doctype': 'Party Type',
+			'party_type': 'Donor',
+			'account_type': 'Receivable'
+		}).insert(ignore_permissions=True)
\ No newline at end of file
diff --git a/erpnext/patches/v13_0/setup_gratuity_rule_for_india_and_uae.py b/erpnext/patches/v13_0/setup_gratuity_rule_for_india_and_uae.py
new file mode 100644
index 0000000..01fd6a1
--- /dev/null
+++ b/erpnext/patches/v13_0/setup_gratuity_rule_for_india_and_uae.py
@@ -0,0 +1,16 @@
+# Copyright (c) 2019, Frappe and Contributors
+# License: GNU General Public License v3. See license.txt
+
+from __future__ import unicode_literals
+import frappe
+
+def execute():
+    frappe.reload_doc('payroll', 'doctype', 'gratuity_rule')
+    frappe.reload_doc('payroll', 'doctype', 'gratuity_rule_slab')
+    frappe.reload_doc('payroll', 'doctype', 'gratuity_applicable_component')
+    if frappe.db.exists("Company", {"country": "India"}):
+        from erpnext.regional.india.setup import create_gratuity_rule
+        create_gratuity_rule()
+    if frappe.db.exists("Company", {"country": "United Arab Emirates"}):
+        from erpnext.regional.united_arab_emirates.setup import create_gratuity_rule
+        create_gratuity_rule()
diff --git a/erpnext/non_profit/doctype/membership_settings/__init__.py b/erpnext/payroll/doctype/gratuity/__init__.py
similarity index 100%
copy from erpnext/non_profit/doctype/membership_settings/__init__.py
copy to erpnext/payroll/doctype/gratuity/__init__.py
diff --git a/erpnext/payroll/doctype/gratuity/gratuity.js b/erpnext/payroll/doctype/gratuity/gratuity.js
new file mode 100644
index 0000000..565d2c4
--- /dev/null
+++ b/erpnext/payroll/doctype/gratuity/gratuity.js
@@ -0,0 +1,72 @@
+// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+frappe.ui.form.on('Gratuity', {
+	setup: function (frm) {
+		frm.set_query('salary_component', function () {
+			return {
+				filters: {
+					type: "Earning"
+				}
+			};
+		});
+		frm.set_query("expense_account", function () {
+			return {
+				filters: {
+					"root_type": "Expense",
+					"is_group": 0,
+					"company": frm.doc.company
+				}
+			};
+		});
+
+		frm.set_query("payable_account", function () {
+			return {
+				filters: {
+					"root_type": "Liability",
+					"is_group": 0,
+					"company": frm.doc.company
+				}
+			};
+		});
+	},
+	refresh: function (frm) {
+		if (frm.doc.docstatus === 1 && frm.doc.pay_via_salary_slip === 0 && frm.doc.status === "Unpaid") {
+			frm.add_custom_button(__("Create Payment Entry"), function () {
+				return frappe.call({
+					method: 'erpnext.accounts.doctype.payment_entry.payment_entry.get_payment_entry',
+					args: {
+						"dt": frm.doc.doctype,
+						"dn": frm.doc.name
+					},
+					callback: function (r) {
+						var doclist = frappe.model.sync(r.message);
+						frappe.set_route("Form", doclist[0].doctype, doclist[0].name);
+					}
+				});
+			});
+		}
+	},
+	employee: function (frm) {
+		frm.events.calculate_work_experience_and_amount(frm);
+	},
+	gratuity_rule: function (frm) {
+		frm.events.calculate_work_experience_and_amount(frm);
+	},
+	calculate_work_experience_and_amount: function (frm) {
+
+		if (frm.doc.employee && frm.doc.gratuity_rule) {
+			frappe.call({
+				method: "erpnext.payroll.doctype.gratuity.gratuity.calculate_work_experience_and_amount",
+				args: {
+					employee: frm.doc.employee,
+					gratuity_rule: frm.doc.gratuity_rule
+				}
+			}).then((r) => {
+				frm.set_value("current_work_experience", r.message['current_work_experience']);
+				frm.set_value("amount", r.message['amount']);
+			});
+		}
+	}
+
+});
\ No newline at end of file
diff --git a/erpnext/payroll/doctype/gratuity/gratuity.json b/erpnext/payroll/doctype/gratuity/gratuity.json
new file mode 100644
index 0000000..5cffd7e
--- /dev/null
+++ b/erpnext/payroll/doctype/gratuity/gratuity.json
@@ -0,0 +1,232 @@
+{
+ "actions": [],
+ "autoname": "HR-GRA-PAY-.#####",
+ "creation": "2020-08-05 20:52:13.024683",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "employee",
+  "employee_name",
+  "department",
+  "designation",
+  "column_break_3",
+  "posting_date",
+  "status",
+  "company",
+  "gratuity_rule",
+  "section_break_5",
+  "pay_via_salary_slip",
+  "payroll_date",
+  "salary_component",
+  "payable_account",
+  "expense_account",
+  "mode_of_payment",
+  "cost_center",
+  "column_break_15",
+  "current_work_experience",
+  "amount",
+  "paid_amount",
+  "amended_from"
+ ],
+ "fields": [
+  {
+   "fieldname": "employee",
+   "fieldtype": "Link",
+   "in_global_search": 1,
+   "in_list_view": 1,
+   "label": "Employee",
+   "options": "Employee",
+   "reqd": 1,
+   "search_index": 1
+  },
+  {
+   "fetch_from": "employee.company",
+   "fieldname": "company",
+   "fieldtype": "Link",
+   "label": "Company",
+   "options": "Company",
+   "read_only": 1,
+   "reqd": 1
+  },
+  {
+   "default": "1",
+   "fieldname": "pay_via_salary_slip",
+   "fieldtype": "Check",
+   "label": "Pay via Salary Slip"
+  },
+  {
+   "fieldname": "posting_date",
+   "fieldtype": "Date",
+   "label": "Posting date",
+   "reqd": 1
+  },
+  {
+   "depends_on": "eval: doc.pay_via_salary_slip == 1",
+   "fieldname": "salary_component",
+   "fieldtype": "Link",
+   "label": "Salary Component",
+   "mandatory_depends_on": "eval: doc.pay_via_salary_slip == 1",
+   "options": "Salary Component"
+  },
+  {
+   "default": "0",
+   "fieldname": "current_work_experience",
+   "fieldtype": "Int",
+   "label": "Current Work Experience",
+   "read_only": 1
+  },
+  {
+   "default": "0",
+   "fieldname": "amount",
+   "fieldtype": "Currency",
+   "label": "Total Amount",
+   "read_only": 1,
+   "reqd": 1
+  },
+  {
+   "default": "Draft",
+   "fieldname": "status",
+   "fieldtype": "Select",
+   "in_list_view": 1,
+   "label": "Status",
+   "options": "Draft\nUnpaid\nPaid",
+   "read_only": 1,
+   "reqd": 1
+  },
+  {
+   "depends_on": "eval: doc.pay_via_salary_slip == 0",
+   "fieldname": "expense_account",
+   "fieldtype": "Link",
+   "label": "Expense Account",
+   "mandatory_depends_on": "eval: doc.pay_via_salary_slip == 0",
+   "options": "Account"
+  },
+  {
+   "depends_on": "eval: doc.pay_via_salary_slip == 0",
+   "fieldname": "mode_of_payment",
+   "fieldtype": "Link",
+   "label": "Mode of Payment",
+   "mandatory_depends_on": "eval: doc.pay_via_salary_slip == 0",
+   "options": "Mode of Payment"
+  },
+  {
+   "fieldname": "gratuity_rule",
+   "fieldtype": "Link",
+   "label": "Gratuity Rule",
+   "options": "Gratuity Rule",
+   "reqd": 1
+  },
+  {
+   "fieldname": "section_break_5",
+   "fieldtype": "Section Break",
+   "label": "Payment Configuration"
+  },
+  {
+   "fetch_from": "employee.employee_name",
+   "fieldname": "employee_name",
+   "fieldtype": "Data",
+   "label": "Employee Name",
+   "read_only": 1
+  },
+  {
+   "fieldname": "column_break_3",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fetch_from": "employee.department",
+   "fieldname": "department",
+   "fieldtype": "Link",
+   "label": "Department",
+   "options": "Department",
+   "read_only": 1
+  },
+  {
+   "fetch_from": "employee.designation",
+   "fieldname": "designation",
+   "fieldtype": "Data",
+   "label": "Designation",
+   "read_only": 1
+  },
+  {
+   "fieldname": "amended_from",
+   "fieldtype": "Link",
+   "label": "Amended From",
+   "no_copy": 1,
+   "options": "Gratuity",
+   "print_hide": 1,
+   "read_only": 1
+  },
+  {
+   "fieldname": "column_break_15",
+   "fieldtype": "Column Break"
+  },
+  {
+   "depends_on": "eval: doc.pay_via_salary_slip == 1",
+   "fieldname": "payroll_date",
+   "fieldtype": "Date",
+   "label": "Payroll Date",
+   "mandatory_depends_on": "eval: doc.pay_via_salary_slip == 1"
+  },
+  {
+   "default": "0",
+   "depends_on": "eval:doc.pay_via_salary_slip == 0",
+   "fieldname": "paid_amount",
+   "fieldtype": "Currency",
+   "label": "Paid Amount",
+   "read_only": 1
+  },
+  {
+   "depends_on": "eval: doc.pay_via_salary_slip == 0",
+   "fieldname": "payable_account",
+   "fieldtype": "Link",
+   "label": "Payable Account",
+   "mandatory_depends_on": "eval: doc.pay_via_salary_slip == 0",
+   "options": "Account"
+  },
+  {
+   "depends_on": "eval: doc.pay_via_salary_slip == 0",
+   "fieldname": "cost_center",
+   "fieldtype": "Link",
+   "label": "Cost Center",
+   "mandatory_depends_on": "eval: doc.pay_via_salary_slip == 0",
+   "options": "Cost Center"
+  }
+ ],
+ "index_web_pages_for_search": 1,
+ "is_submittable": 1,
+ "links": [],
+ "modified": "2020-11-02 18:21:11.971488",
+ "modified_by": "Administrator",
+ "module": "Payroll",
+ "name": "Gratuity",
+ "owner": "Administrator",
+ "permissions": [
+  {
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "export": 1,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "HR Manager",
+   "share": 1,
+   "write": 1
+  },
+  {
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "export": 1,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "HR User",
+   "share": 1,
+   "write": 1
+  }
+ ],
+ "sort_field": "modified",
+ "sort_order": "DESC"
+}
\ No newline at end of file
diff --git a/erpnext/payroll/doctype/gratuity/gratuity.py b/erpnext/payroll/doctype/gratuity/gratuity.py
new file mode 100644
index 0000000..1acd6e3
--- /dev/null
+++ b/erpnext/payroll/doctype/gratuity/gratuity.py
@@ -0,0 +1,249 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe import _, bold
+from frappe.utils import flt, get_datetime, get_link_to_form
+from erpnext.accounts.general_ledger import make_gl_entries
+from erpnext.controllers.accounts_controller import AccountsController
+from math import floor
+
+class Gratuity(AccountsController):
+	def validate(self):
+		data = calculate_work_experience_and_amount(self.employee, self.gratuity_rule)
+		self.current_work_experience = data["current_work_experience"]
+		self.amount = data["amount"]
+		if self.docstatus == 1:
+			self.status = "Unpaid"
+
+	def on_submit(self):
+		if self.pay_via_salary_slip:
+			self.create_additional_salary()
+		else:
+			self.create_gl_entries()
+
+	def on_cancel(self):
+		self.ignore_linked_doctypes = ['GL Entry']
+		self.create_gl_entries(cancel=True)
+
+	def create_gl_entries(self, cancel=False):
+		gl_entries = self.get_gl_entries()
+		make_gl_entries(gl_entries, cancel)
+
+	def get_gl_entries(self):
+		gl_entry = []
+		# payable entry
+		if self.amount:
+			gl_entry.append(
+				self.get_gl_dict({
+					"account": self.payable_account,
+					"credit": self.amount,
+					"credit_in_account_currency": self.amount,
+					"against": self.expense_account,
+					"party_type": "Employee",
+					"party": self.employee,
+					"against_voucher_type": self.doctype,
+					"against_voucher": self.name,
+					"cost_center": self.cost_center
+				}, item=self)
+			)
+
+			# expense entries
+			gl_entry.append(
+				self.get_gl_dict({
+					"account": self.expense_account,
+					"debit": self.amount,
+					"debit_in_account_currency": self.amount,
+					"against": self.payable_account,
+					"cost_center": self.cost_center
+				}, item=self)
+			)
+		else:
+			frappe.throw(_("Total Amount can not be zero"))
+
+		return gl_entry
+
+	def create_additional_salary(self):
+		if self.pay_via_salary_slip:
+			additional_salary = frappe.new_doc('Additional Salary')
+			additional_salary.employee = self.employee
+			additional_salary.salary_component = self.salary_component
+			additional_salary.overwrite_salary_structure_amount = 0
+			additional_salary.amount = self.amount
+			additional_salary.payroll_date = self.payroll_date
+			additional_salary.company = self.company
+			additional_salary.ref_doctype = self.doctype
+			additional_salary.ref_docname = self.name
+			additional_salary.submit()
+
+	def set_total_advance_paid(self):
+		paid_amount = frappe.db.sql("""
+			select ifnull(sum(debit_in_account_currency), 0) as paid_amount
+			from `tabGL Entry`
+			where against_voucher_type = 'Gratuity'
+				and against_voucher = %s
+				and party_type = 'Employee'
+				and party = %s
+		""", (self.name, self.employee), as_dict=1)[0].paid_amount
+
+		if flt(paid_amount) > self.amount:
+			frappe.throw(_("Row {0}# Paid Amount cannot be greater than Total amount"))
+
+
+		self.db_set("paid_amount", paid_amount)
+		if self.amount == self.paid_amount:
+			self.db_set("status", "Paid")
+
+
+@frappe.whitelist()
+def calculate_work_experience_and_amount(employee, gratuity_rule):
+	current_work_experience = calculate_work_experience(employee, gratuity_rule) or 0
+	gratuity_amount = calculate_gratuity_amount(employee, gratuity_rule, current_work_experience) or 0
+
+	return {'current_work_experience': current_work_experience, "amount": gratuity_amount}
+
+def calculate_work_experience(employee, gratuity_rule):
+
+	total_working_days_per_year, minimum_year_for_gratuity = frappe.db.get_value("Gratuity Rule", gratuity_rule, ["total_working_days_per_year", "minimum_year_for_gratuity"])
+
+	date_of_joining, relieving_date = frappe.db.get_value('Employee', employee, ['date_of_joining', 'relieving_date'])
+	if not relieving_date:
+		frappe.throw(_("Please set Relieving Date for employee: {0}").format(bold(get_link_to_form("Employee", employee))))
+
+	method = frappe.db.get_value("Gratuity Rule", gratuity_rule, "work_experience_calculation_function")
+	employee_total_workings_days = calculate_employee_total_workings_days(employee, date_of_joining, relieving_date)
+
+	current_work_experience = employee_total_workings_days/total_working_days_per_year or 1
+	current_work_experience = get_work_experience_using_method(method, current_work_experience, minimum_year_for_gratuity, employee)
+	return current_work_experience
+
+def calculate_employee_total_workings_days(employee, date_of_joining, relieving_date ):
+	employee_total_workings_days = (get_datetime(relieving_date) - get_datetime(date_of_joining)).days
+
+	payroll_based_on = frappe.db.get_value("Payroll Settings", None, "payroll_based_on") or "Leave"
+	if payroll_based_on == "Leave":
+		total_lwp = get_non_working_days(employee, relieving_date, "On Leave")
+		employee_total_workings_days -= total_lwp
+	elif  payroll_based_on == "Attendance":
+		total_absents = get_non_working_days(employee, relieving_date, "Absent")
+		employee_total_workings_days -= total_absents
+
+	return employee_total_workings_days
+
+def get_work_experience_using_method(method, current_work_experience, minimum_year_for_gratuity, employee):
+	if method == "Round off Work Experience":
+		current_work_experience = round(current_work_experience)
+	else:
+		current_work_experience = floor(current_work_experience)
+
+	if current_work_experience < minimum_year_for_gratuity:
+		frappe.throw(_("Employee: {0} have to complete minimum {1} years for gratuity").format(bold(employee), minimum_year_for_gratuity))
+	return current_work_experience
+
+def get_non_working_days(employee, relieving_date, status):
+
+	filters={
+			"docstatus": 1,
+			"status": status,
+			"employee": employee,
+			"attendance_date": ("<=", get_datetime(relieving_date))
+		}
+
+	if status == "On Leave":
+		lwp_leave_types =  frappe.get_list("Leave Type", filters = {"is_lwp":1})
+		lwp_leave_types = [leave_type.name for leave_type in lwp_leave_types]
+		filters["leave_type"] =  ("IN", lwp_leave_types)
+
+
+	record = frappe.get_all("Attendance", filters=filters, fields = ["COUNT(name) as total_lwp"])
+	return record[0].total_lwp if len(record) else 0
+
+def calculate_gratuity_amount(employee, gratuity_rule, experience):
+	applicable_earnings_component = get_applicable_components(gratuity_rule)
+	total_applicable_components_amount = get_total_applicable_component_amount(employee, applicable_earnings_component, gratuity_rule)
+
+	calculate_gratuity_amount_based_on = frappe.db.get_value("Gratuity Rule", gratuity_rule, "calculate_gratuity_amount_based_on")
+	gratuity_amount = 0
+	slabs = get_gratuity_rule_slabs(gratuity_rule)
+	slab_found = False
+	year_left = experience
+
+	for slab in slabs:
+		if calculate_gratuity_amount_based_on == "Current Slab":
+			slab_found, gratuity_amount = calculate_amount_based_on_current_slab(slab.from_year, slab.to_year,
+				experience, total_applicable_components_amount, slab.fraction_of_applicable_earnings)
+			if slab_found:
+					break
+
+		elif calculate_gratuity_amount_based_on == "Sum of all previous slabs":
+			if slab.to_year == 0 and slab.from_year == 0:
+				gratuity_amount += year_left * total_applicable_components_amount * slab.fraction_of_applicable_earnings
+				slab_found = True
+				break
+
+			if experience > slab.to_year and experience > slab.from_year and slab.to_year !=0:
+				gratuity_amount += (slab.to_year - slab.from_year) * total_applicable_components_amount * slab.fraction_of_applicable_earnings
+				year_left -= (slab.to_year - slab.from_year)
+				slab_found = True
+			elif slab.from_year <= experience and (experience < slab.to_year or slab.to_year == 0):
+				gratuity_amount += year_left * total_applicable_components_amount * slab.fraction_of_applicable_earnings
+				slab_found = True
+
+	if not slab_found:
+		frappe.throw(_("No Suitable Slab found for Calculation of gratuity amount in Gratuity Rule: {0}").format(bold(gratuity_rule)))
+	return gratuity_amount
+
+def get_applicable_components(gratuity_rule):
+	applicable_earnings_component = frappe.get_all("Gratuity Applicable Component", filters= {'parent': gratuity_rule}, fields=["salary_component"])
+	if len(applicable_earnings_component) == 0:
+		frappe.throw(_("No Applicable Earnings Component found for Gratuity Rule: {0}").format(bold(get_link_to_form("Gratuity Rule",gratuity_rule))))
+	applicable_earnings_component = [component.salary_component for component in applicable_earnings_component]
+
+	return applicable_earnings_component
+
+def get_total_applicable_component_amount(employee, applicable_earnings_component, gratuity_rule):
+	sal_slip  = get_last_salary_slip(employee)
+	if not sal_slip:
+		frappe.throw(_("No Salary Slip is found for Employee: {0}").format(bold(employee)))
+	component_and_amounts = frappe.get_list("Salary Detail",
+		filters={
+			"docstatus": 1,
+			'parent': sal_slip,
+			"parentfield": "earnings",
+			'salary_component': ('in', applicable_earnings_component)
+		},
+		fields=["amount"])
+	total_applicable_components_amount = 0
+	if not len(component_and_amounts):
+		frappe.throw(_("No Applicable Component is present in last month salary slip"))
+	for data in component_and_amounts:
+		total_applicable_components_amount += data.amount
+	return total_applicable_components_amount
+
+def calculate_amount_based_on_current_slab(from_year, to_year, experience, total_applicable_components_amount, fraction_of_applicable_earnings):
+	slab_found = False; gratuity_amount = 0
+	if experience >= from_year and (to_year == 0 or experience < to_year):
+		gratuity_amount = total_applicable_components_amount * experience * fraction_of_applicable_earnings
+		if fraction_of_applicable_earnings:
+			slab_found = True
+
+	return slab_found, gratuity_amount
+
+def get_gratuity_rule_slabs(gratuity_rule):
+	return frappe.get_all("Gratuity Rule Slab", filters= {'parent': gratuity_rule}, fields = ["*"], order_by="idx")
+
+def get_salary_structure(employee):
+	return frappe.get_list("Salary Structure Assignment", filters = {
+			"employee": employee, 'docstatus': 1
+		},
+		fields=["from_date", "salary_structure"],
+		order_by = "from_date desc")[0].salary_structure
+
+def get_last_salary_slip(employee):
+	return frappe.get_list("Salary Slip", filters = {
+			"employee": employee, 'docstatus': 1
+		},
+		order_by = "start_date desc")[0].name
+
diff --git a/erpnext/payroll/doctype/gratuity/gratuity_dashboard.py b/erpnext/payroll/doctype/gratuity/gratuity_dashboard.py
new file mode 100644
index 0000000..5b2489f
--- /dev/null
+++ b/erpnext/payroll/doctype/gratuity/gratuity_dashboard.py
@@ -0,0 +1,20 @@
+from __future__ import unicode_literals
+from frappe import _
+
+def get_data():
+	return {
+		'fieldname': 'reference_name',
+		'non_standard_fieldnames': {
+			'Additional Salary': 'ref_docname',
+		},
+		'transactions': [
+			{
+				'label': _('Payment'),
+				'items': ['Payment Entry']
+			},
+			{
+				'label': _('Additional Salary'),
+				'items': ['Additional Salary']
+			}
+		]
+	}
\ No newline at end of file
diff --git a/erpnext/payroll/doctype/gratuity/test_gratuity.py b/erpnext/payroll/doctype/gratuity/test_gratuity.py
new file mode 100644
index 0000000..e89e3dd
--- /dev/null
+++ b/erpnext/payroll/doctype/gratuity/test_gratuity.py
@@ -0,0 +1,192 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
+# See license.txt
+from __future__ import unicode_literals
+
+import frappe
+import unittest
+from erpnext.hr.doctype.employee.test_employee import make_employee
+from erpnext.payroll.doctype.salary_slip.test_salary_slip import make_employee_salary_slip, make_earning_salary_component, \
+	make_deduction_salary_component
+from erpnext.payroll.doctype.gratuity.gratuity import get_last_salary_slip
+from erpnext.regional.united_arab_emirates.setup import create_gratuity_rule
+from erpnext.hr.doctype.expense_claim.test_expense_claim import get_payable_account
+from frappe.utils import getdate, add_days, get_datetime, flt
+
+test_dependencies = ["Salary Component", "Salary Slip", "Account"]
+class TestGratuity(unittest.TestCase):
+	def setUp(self):
+		make_earning_salary_component(setup=True, test_tax=True, company_list=['_Test Company'])
+		make_deduction_salary_component(setup=True, test_tax=True, company_list=['_Test Company'])
+		frappe.db.sql("DELETE FROM `tabGratuity`")
+		frappe.db.sql("DELETE FROM `tabAdditional Salary` WHERE ref_doctype = 'Gratuity'")
+
+	def test_check_gratuity_amount_based_on_current_slab_and_additional_salary_creation(self):
+		employee, sal_slip = create_employee_and_get_last_salary_slip()
+
+		rule = get_gratuity_rule("Rule Under Unlimited Contract on termination (UAE)")
+
+		gratuity = create_gratuity(pay_via_salary_slip = 1, employee=employee, rule=rule.name)
+
+		#work experience calculation
+		date_of_joining, relieving_date = frappe.db.get_value('Employee', employee, ['date_of_joining', 'relieving_date'])
+		employee_total_workings_days = (get_datetime(relieving_date) - get_datetime(date_of_joining)).days
+
+		experience = employee_total_workings_days/rule.total_working_days_per_year
+		gratuity.reload()
+		from math import floor
+		self.assertEqual(floor(experience), gratuity.current_work_experience)
+
+		#amount Calculation
+		component_amount = frappe.get_list("Salary Detail",
+		filters={
+			"docstatus": 1,
+			'parent': sal_slip,
+			"parentfield": "earnings",
+			'salary_component': "Basic Salary"
+		},
+		fields=["amount"])
+
+		''' 5 - 0 fraction is 1 '''
+
+		gratuity_amount = component_amount[0].amount * experience
+		gratuity.reload()
+
+		self.assertEqual(flt(gratuity_amount, 2), flt(gratuity.amount, 2))
+
+		#additional salary creation (Pay via salary slip)
+		self.assertTrue(frappe.db.exists("Additional Salary", {"ref_docname": gratuity.name}))
+
+	def test_check_gratuity_amount_based_on_all_previous_slabs(self):
+		employee, sal_slip = create_employee_and_get_last_salary_slip()
+		rule = get_gratuity_rule("Rule Under Limited Contract (UAE)")
+		set_mode_of_payment_account()
+
+		gratuity = create_gratuity(expense_account = 'Payment Account - _TC', mode_of_payment='Cash', employee=employee)
+
+		#work experience calculation
+		date_of_joining, relieving_date = frappe.db.get_value('Employee', employee, ['date_of_joining', 'relieving_date'])
+		employee_total_workings_days = (get_datetime(relieving_date) - get_datetime(date_of_joining)).days
+
+		experience = employee_total_workings_days/rule.total_working_days_per_year
+
+		gratuity.reload()
+
+		from math import floor
+
+		self.assertEqual(floor(experience), gratuity.current_work_experience)
+
+		#amount Calculation
+		component_amount = frappe.get_list("Salary Detail",
+		filters={
+			"docstatus": 1,
+			'parent': sal_slip,
+			"parentfield": "earnings",
+			'salary_component': "Basic Salary"
+		},
+		fields=["amount"])
+
+		''' range  | Fraction
+			0-1    |    0
+			1-5    |   0.7
+			5-0    |    1
+		'''
+
+		gratuity_amount = ((0 * 1) + (4 * 0.7) + (1 * 1)) *  component_amount[0].amount
+		gratuity.reload()
+
+		self.assertEqual(flt(gratuity_amount, 2), flt(gratuity.amount, 2))
+		self.assertEqual(gratuity.status, "Unpaid")
+
+		from erpnext.accounts.doctype.payment_entry.payment_entry import get_payment_entry
+		pay_entry = get_payment_entry("Gratuity", gratuity.name)
+		pay_entry.reference_no = "123467"
+		pay_entry.reference_date = getdate()
+		pay_entry.save()
+		pay_entry.submit()
+		gratuity.reload()
+
+		self.assertEqual(gratuity.status, "Paid")
+		self.assertEqual(flt(gratuity.paid_amount,2), flt(gratuity.amount, 2))
+
+	def tearDown(self):
+		frappe.db.sql("DELETE FROM `tabGratuity`")
+		frappe.db.sql("DELETE FROM `tabAdditional Salary` WHERE ref_doctype = 'Gratuity'")
+
+def get_gratuity_rule(name):
+	rule = frappe.db.exists("Gratuity Rule", name)
+	if not rule:
+		create_gratuity_rule()
+	rule = frappe.get_doc("Gratuity Rule", name)
+	rule.applicable_earnings_component = []
+	rule.append("applicable_earnings_component", {
+		"salary_component": "Basic Salary"
+	})
+	rule.save()
+	rule.reload()
+
+	return rule
+
+def create_gratuity(**args):
+	if args:
+		args = frappe._dict(args)
+	gratuity = frappe.new_doc("Gratuity")
+	gratuity.employee = args.employee
+	gratuity.posting_date = getdate()
+	gratuity.gratuity_rule = args.rule or "Rule Under Limited Contract (UAE)"
+	gratuity.pay_via_salary_slip = args.pay_via_salary_slip or 0
+	if gratuity.pay_via_salary_slip:
+		gratuity.payroll_date = getdate()
+		gratuity.salary_component = "Performance Bonus"
+	else:
+		gratuity.expense_account =  args.expense_account or 'Payment Account - _TC'
+		gratuity.payable_account = args.payable_account or get_payable_account("_Test Company")
+		gratuity.mode_of_payment = args.mode_of_payment or 'Cash'
+
+	gratuity.save()
+	gratuity.submit()
+
+	return gratuity
+
+def set_mode_of_payment_account():
+	if not frappe.db.exists("Account", "Payment Account - _TC"):
+		mode_of_payment = create_account()
+
+	mode_of_payment = frappe.get_doc("Mode of Payment", "Cash")
+
+	mode_of_payment.accounts = []
+	mode_of_payment.append("accounts", {
+		"company": "_Test Company",
+		"default_account": "_Test Bank - _TC"
+	})
+	mode_of_payment.save()
+
+def create_account():
+	return frappe.get_doc({
+			"doctype": "Account",
+			"company": "_Test Company",
+			"account_name": "Payment Account",
+			"root_type": "Asset",
+			"report_type": "Balance Sheet",
+			"currency": "INR",
+			"parent_account": "Bank Accounts - _TC",
+			"account_type": "Bank",
+		}).insert(ignore_permissions=True)
+
+def create_employee_and_get_last_salary_slip():
+	employee = make_employee("test_employee@salary.com", company='_Test Company')
+	frappe.db.set_value("Employee", employee, "relieving_date", getdate())
+	frappe.db.set_value("Employee", employee, "date_of_joining", add_days(getdate(), - (6*365)))
+	if not frappe.db.exists("Salary Slip", {"employee":employee}):
+		salary_slip = make_employee_salary_slip("test_employee@salary.com", "Monthly")
+		salary_slip.submit()
+		salary_slip = salary_slip.name
+	else:
+		salary_slip = get_last_salary_slip(employee)
+
+	if not frappe.db.get_value("Employee", "test_employee@salary.com", "holiday_list"):
+		from erpnext.payroll.doctype.salary_slip.test_salary_slip import make_holiday_list
+		make_holiday_list()
+		frappe.db.set_value("Company", '_Test Company', "default_holiday_list", "Salary Slip Test Holiday List")
+
+	return employee, salary_slip
diff --git a/erpnext/non_profit/doctype/membership_settings/__init__.py b/erpnext/payroll/doctype/gratuity_applicable_component/__init__.py
similarity index 100%
copy from erpnext/non_profit/doctype/membership_settings/__init__.py
copy to erpnext/payroll/doctype/gratuity_applicable_component/__init__.py
diff --git a/erpnext/payroll/doctype/gratuity_applicable_component/gratuity_applicable_component.json b/erpnext/payroll/doctype/gratuity_applicable_component/gratuity_applicable_component.json
new file mode 100644
index 0000000..eea0e85
--- /dev/null
+++ b/erpnext/payroll/doctype/gratuity_applicable_component/gratuity_applicable_component.json
@@ -0,0 +1,32 @@
+{
+ "actions": [],
+ "creation": "2020-08-05 19:00:28.097265",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "salary_component"
+ ],
+ "fields": [
+  {
+   "fieldname": "salary_component",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "label": "Salary Component ",
+   "options": "Salary Component",
+   "reqd": 1
+  }
+ ],
+ "istable": 1,
+ "links": [],
+ "modified": "2020-08-05 20:17:13.855035",
+ "modified_by": "Administrator",
+ "module": "Payroll",
+ "name": "Gratuity Applicable Component",
+ "owner": "Administrator",
+ "permissions": [],
+ "quick_entry": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/payroll/doctype/gratuity_applicable_component/gratuity_applicable_component.py b/erpnext/payroll/doctype/gratuity_applicable_component/gratuity_applicable_component.py
new file mode 100644
index 0000000..23e4340
--- /dev/null
+++ b/erpnext/payroll/doctype/gratuity_applicable_component/gratuity_applicable_component.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+# import frappe
+from frappe.model.document import Document
+
+class GratuityApplicableComponent(Document):
+	pass
diff --git a/erpnext/non_profit/doctype/membership_settings/__init__.py b/erpnext/payroll/doctype/gratuity_rule/__init__.py
similarity index 100%
copy from erpnext/non_profit/doctype/membership_settings/__init__.py
copy to erpnext/payroll/doctype/gratuity_rule/__init__.py
diff --git a/erpnext/payroll/doctype/gratuity_rule/gratuity_rule.js b/erpnext/payroll/doctype/gratuity_rule/gratuity_rule.js
new file mode 100644
index 0000000..ee6c5df
--- /dev/null
+++ b/erpnext/payroll/doctype/gratuity_rule/gratuity_rule.js
@@ -0,0 +1,40 @@
+// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+frappe.ui.form.on('Gratuity Rule', {
+	// refresh: function(frm) {
+
+	// }
+});
+
+frappe.ui.form.on('Gratuity Rule Slab', {
+
+	/*
+		Slabs should be in order like
+
+		from | to | fraction
+		0    | 4  | 0.5
+		4    | 6  | 0.7
+
+		So, on row addition setting current_row.from = previous row.to.
+		On to_year insert we have to check that it is not less than from_year
+
+		Wrong order may lead to Wrong Calculation
+	*/
+
+	gratuity_rule_slabs_add(frm, cdt, cdn) {
+		let row = locals[cdt][cdn];
+		let array_idx = row.idx - 1;
+		if (array_idx > 0) {
+			row.from_year = cur_frm.doc.gratuity_rule_slabs[array_idx - 1].to_year;
+			frm.refresh();
+		}
+	},
+
+	to_year(frm, cdt, cdn) {
+		let row = locals[cdt][cdn];
+		if (row.to_year <= row.from_year && row.to_year === 0) {
+			frappe.throw(__("To(Year) year can not be less than From(year) "));
+		}
+	}
+});
\ No newline at end of file
diff --git a/erpnext/payroll/doctype/gratuity_rule/gratuity_rule.json b/erpnext/payroll/doctype/gratuity_rule/gratuity_rule.json
new file mode 100644
index 0000000..84cdcf5
--- /dev/null
+++ b/erpnext/payroll/doctype/gratuity_rule/gratuity_rule.json
@@ -0,0 +1,114 @@
+{
+ "actions": [],
+ "autoname": "Prompt",
+ "creation": "2020-08-05 19:00:36.103500",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "applicable_earnings_component",
+  "work_experience_calculation_function",
+  "total_working_days_per_year",
+  "column_break_3",
+  "disable",
+  "calculate_gratuity_amount_based_on",
+  "minimum_year_for_gratuity",
+  "gratuity_rules_section",
+  "gratuity_rule_slabs"
+ ],
+ "fields": [
+  {
+   "default": "0",
+   "fieldname": "disable",
+   "fieldtype": "Check",
+   "label": "Disable"
+  },
+  {
+   "fieldname": "calculate_gratuity_amount_based_on",
+   "fieldtype": "Select",
+   "in_list_view": 1,
+   "label": "Calculate Gratuity Amount Based On",
+   "options": "Current Slab\nSum of all previous slabs",
+   "reqd": 1
+  },
+  {
+   "description": "Salary components should be part of the Salary Structure.",
+   "fieldname": "applicable_earnings_component",
+   "fieldtype": "Table MultiSelect",
+   "label": "Applicable Earnings Component",
+   "options": "Gratuity Applicable Component",
+   "reqd": 1
+  },
+  {
+   "fieldname": "column_break_3",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "gratuity_rules_section",
+   "fieldtype": "Section Break",
+   "label": "Gratuity Rules"
+  },
+  {
+   "description": "Leave <b>From</b> and <b>To</b> 0 for no upper and lower limit.",
+   "fieldname": "gratuity_rule_slabs",
+   "fieldtype": "Table",
+   "label": "Current Work Experience",
+   "options": "Gratuity Rule Slab",
+   "reqd": 1
+  },
+  {
+   "default": "Round off Work Experience",
+   "fieldname": "work_experience_calculation_function",
+   "fieldtype": "Select",
+   "label": "Work Experience Calculation method",
+   "options": "Round off Work Experience\nTake Exact Completed Years"
+  },
+  {
+   "default": "365",
+   "fieldname": "total_working_days_per_year",
+   "fieldtype": "Int",
+   "label": "Total working Days Per Year"
+  },
+  {
+   "fieldname": "minimum_year_for_gratuity",
+   "fieldtype": "Int",
+   "label": "Minimum Year for Gratuity"
+  }
+ ],
+ "index_web_pages_for_search": 1,
+ "links": [],
+ "modified": "2020-12-03 17:08:27.891535",
+ "modified_by": "Administrator",
+ "module": "Payroll",
+ "name": "Gratuity Rule",
+ "owner": "Administrator",
+ "permissions": [
+  {
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "export": 1,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "HR Manager",
+   "share": 1,
+   "write": 1
+  },
+  {
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "export": 1,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "HR User",
+   "share": 1,
+   "write": 1
+  }
+ ],
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/payroll/doctype/gratuity_rule/gratuity_rule.py b/erpnext/payroll/doctype/gratuity_rule/gratuity_rule.py
new file mode 100644
index 0000000..29a6ebe
--- /dev/null
+++ b/erpnext/payroll/doctype/gratuity_rule/gratuity_rule.py
@@ -0,0 +1,33 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe.model.document import Document
+from frappe import _
+
+class GratuityRule(Document):
+
+	def validate(self):
+		for current_slab in self.gratuity_rule_slabs:
+			if (current_slab.from_year > current_slab.to_year) and current_slab.to_year != 0:
+				frappe(_("Row {0}: From (Year) can not be greater than To (Year)").format(current_slab.idx))
+
+			if current_slab.to_year == 0 and current_slab.from_year == 0 and len(self.gratuity_rule_slabs) > 1:
+				frappe.throw(_("You can not define multiple slabs if you have a slab with no lower and upper limits."))
+
+def get_gratuity_rule(name, slabs, **args):
+	args = frappe._dict(args)
+
+	rule = frappe.new_doc("Gratuity Rule")
+	rule.name = name
+	rule.calculate_gratuity_amount_based_on = args.calculate_gratuity_amount_based_on or "Current Slab"
+	rule.work_experience_calculation_method = args.work_experience_calculation_method or "Take Exact Completed Years"
+	rule.minimum_year_for_gratuity = 1
+
+
+	for slab in slabs:
+		slab = frappe._dict(slab)
+		rule.append("gratuity_rule_slabs", slab)
+	return rule
diff --git a/erpnext/payroll/doctype/gratuity_rule/gratuity_rule_dashboard.py b/erpnext/payroll/doctype/gratuity_rule/gratuity_rule_dashboard.py
new file mode 100644
index 0000000..0d70163
--- /dev/null
+++ b/erpnext/payroll/doctype/gratuity_rule/gratuity_rule_dashboard.py
@@ -0,0 +1,13 @@
+from __future__ import unicode_literals
+from frappe import _
+
+def get_data():
+	return {
+		'fieldname': 'gratuity_rule',
+		'transactions': [
+			{
+				'label': _('Gratuity'),
+				'items': ['Gratuity']
+			}
+		]
+	}
\ No newline at end of file
diff --git a/erpnext/non_profit/doctype/membership_settings/test_membership_settings.py b/erpnext/payroll/doctype/gratuity_rule/test_gratuity_rule.py
similarity index 78%
copy from erpnext/non_profit/doctype/membership_settings/test_membership_settings.py
copy to erpnext/payroll/doctype/gratuity_rule/test_gratuity_rule.py
index 2ad7984..1f5dc4e 100644
--- a/erpnext/non_profit/doctype/membership_settings/test_membership_settings.py
+++ b/erpnext/payroll/doctype/gratuity_rule/test_gratuity_rule.py
@@ -6,5 +6,5 @@
 # import frappe
 import unittest
 
-class TestMembershipSettings(unittest.TestCase):
+class TestGratuityRule(unittest.TestCase):
 	pass
diff --git a/erpnext/non_profit/doctype/membership_settings/__init__.py b/erpnext/payroll/doctype/gratuity_rule_slab/__init__.py
similarity index 100%
copy from erpnext/non_profit/doctype/membership_settings/__init__.py
copy to erpnext/payroll/doctype/gratuity_rule_slab/__init__.py
diff --git a/erpnext/payroll/doctype/gratuity_rule_slab/gratuity_rule_slab.json b/erpnext/payroll/doctype/gratuity_rule_slab/gratuity_rule_slab.json
new file mode 100644
index 0000000..bc37b0f
--- /dev/null
+++ b/erpnext/payroll/doctype/gratuity_rule_slab/gratuity_rule_slab.json
@@ -0,0 +1,50 @@
+{
+ "actions": [],
+ "creation": "2020-08-05 19:12:49.423500",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "from_year",
+  "to_year",
+  "fraction_of_applicable_earnings"
+ ],
+ "fields": [
+  {
+   "fieldname": "fraction_of_applicable_earnings",
+   "fieldtype": "Float",
+   "in_list_view": 1,
+   "label": "Fraction of Applicable Earnings ",
+   "reqd": 1
+  },
+  {
+   "default": "0",
+   "fieldname": "from_year",
+   "fieldtype": "Int",
+   "in_list_view": 1,
+   "label": "From(Year)",
+   "read_only": 1,
+   "reqd": 1
+  },
+  {
+   "default": "0",
+   "fieldname": "to_year",
+   "fieldtype": "Int",
+   "in_list_view": 1,
+   "label": "To(Year)",
+   "reqd": 1
+  }
+ ],
+ "istable": 1,
+ "links": [],
+ "modified": "2020-08-17 14:09:56.781712",
+ "modified_by": "Administrator",
+ "module": "Payroll",
+ "name": "Gratuity Rule Slab",
+ "owner": "Administrator",
+ "permissions": [],
+ "quick_entry": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/payroll/doctype/gratuity_rule_slab/gratuity_rule_slab.py b/erpnext/payroll/doctype/gratuity_rule_slab/gratuity_rule_slab.py
new file mode 100644
index 0000000..fa468e7
--- /dev/null
+++ b/erpnext/payroll/doctype/gratuity_rule_slab/gratuity_rule_slab.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+# import frappe
+from frappe.model.document import Document
+
+class GratuityRuleSlab(Document):
+	pass
diff --git a/erpnext/payroll/doctype/salary_slip/salary_slip.py b/erpnext/payroll/doctype/salary_slip/salary_slip.py
index d9aadbf..595d697 100644
--- a/erpnext/payroll/doctype/salary_slip/salary_slip.py
+++ b/erpnext/payroll/doctype/salary_slip/salary_slip.py
@@ -80,9 +80,26 @@
 			if (frappe.db.get_single_value("Payroll Settings", "email_salary_slip_to_employee")) and not frappe.flags.via_payroll_entry:
 				self.email_salary_slip()
 
+		self.update_payment_status_for_gratuity()
+
+	def update_payment_status_for_gratuity(self):
+		add_salary = frappe.db.get_all("Additional Salary",
+			filters = {
+				"payroll_date": ("BETWEEN", [self.start_date, self.end_date]),
+				"employee": self.employee,
+				"ref_doctype": "Gratuity",
+				"docstatus": 1,
+			}, fields = ["ref_docname", "name"], limit=1)
+
+		if len(add_salary):
+			status = "Paid" if self.docstatus == 1 else "Unpaid"
+			if add_salary[0].name in [data.additional_salary for data in self.earnings]:
+				frappe.db.set_value("Gratuity", add_salary.ref_docname, "status", status)
+
 	def on_cancel(self):
 		self.set_status()
 		self.update_status()
+		self.update_payment_status_for_gratuity()
 		self.cancel_loan_repayment_entry()
 
 	def on_trash(self):
@@ -506,7 +523,8 @@
 			return amount
 
 		except NameError as err:
-			frappe.throw(_("Name error: {0}").format(err))
+			frappe.throw(_("{0} <br> This error can be due to missing or deleted field.").format(err),
+			    title=_("Name error"))
 		except SyntaxError as err:
 			frappe.throw(_("Syntax error in formula or condition: {0}").format(err))
 		except Exception as e:
@@ -573,6 +591,7 @@
 		for d in self.get(key):
 			if d.salary_component == struct_row.salary_component:
 				component_row = d
+
 		if not component_row or (struct_row.get("is_additional_component") and not overwrite):
 			if amount:
 				self.append(key, {
@@ -930,7 +949,8 @@
 			if condition:
 				return frappe.safe_eval(condition, self.whitelisted_globals, data)
 		except NameError as err:
-			frappe.throw(_("Name error: {0}").format(err))
+			frappe.throw(_("{0} <br> This error can be due to missing or deleted field.").format(err),
+			    title=_("Name error"))
 		except SyntaxError as err:
 			frappe.throw(_("Syntax error in condition: {0}").format(err))
 		except Exception as e:
@@ -1242,4 +1262,4 @@
 
 def generate_password_for_pdf(policy_template, employee):
 	employee = frappe.get_doc("Employee", employee)
-	return policy_template.format(**employee.as_dict())
\ No newline at end of file
+	return policy_template.format(**employee.as_dict())
diff --git a/erpnext/payroll/doctype/salary_slip/test_salary_slip.py b/erpnext/payroll/doctype/salary_slip/test_salary_slip.py
index f58a8e5..143a306 100644
--- a/erpnext/payroll/doctype/salary_slip/test_salary_slip.py
+++ b/erpnext/payroll/doctype/salary_slip/test_salary_slip.py
@@ -21,6 +21,7 @@
 class TestSalarySlip(unittest.TestCase):
 	def setUp(self):
 		setup_test()
+
 	def tearDown(self):
 		frappe.db.set_value("Payroll Settings", None, "include_holidays_in_total_working_days", 0)
 		frappe.set_user("Administrator")
@@ -245,7 +246,7 @@
 		make_salary_structure("Test Loan Repayment Salary Structure", "Monthly", employee=applicant, currency='INR',
 			payroll_period=payroll_period)
 
-		frappe.db.sql("""delete from `tabLoan""")
+		frappe.db.sql("delete from tabLoan")
 		loan = create_loan(applicant, "Car Loan", 11000, "Repay Over Number of Periods", 20, posting_date=add_months(nowdate(), -1))
 		loan.repay_from_salary = 1
 		loan.submit()
diff --git a/erpnext/payroll/doctype/salary_structure/salary_structure.js b/erpnext/payroll/doctype/salary_structure/salary_structure.js
index 1378bf0..6aa1387 100755
--- a/erpnext/payroll/doctype/salary_structure/salary_structure.js
+++ b/erpnext/payroll/doctype/salary_structure/salary_structure.js
@@ -142,6 +142,8 @@
 			],
 			primary_action: function() {
 				var data = d.get_values();
+				delete data.company
+				delete data.currency
 				frappe.call({
 					doc: frm.doc,
 					method: "assign_salary_structure",
diff --git a/erpnext/public/js/controllers/buying.js b/erpnext/public/js/controllers/buying.js
index c963866..cdfd909 100644
--- a/erpnext/public/js/controllers/buying.js
+++ b/erpnext/public/js/controllers/buying.js
@@ -141,29 +141,6 @@
 		this.apply_price_list();
 	},
 
-	price_list_rate: function(doc, cdt, cdn) {
-		var item = frappe.get_doc(cdt, cdn);
-
-		frappe.model.round_floats_in(item, ["price_list_rate", "discount_percentage"]);
-
-		let item_rate = item.price_list_rate;
-		if (doc.doctype == "Purchase Order" && item.blanket_order_rate) {
-			item_rate = item.blanket_order_rate;
-		}
-
-		if (item.discount_percentage) {
-			item.discount_amount = flt(item_rate) * flt(item.discount_percentage) / 100;
-		}
-
-		if (item.discount_amount) {
-			item.rate = flt((item.price_list_rate) - (item.discount_amount), precision('rate', item));
-		} else {
-			item.rate = item_rate;
-		}
-
-		this.calculate_taxes_and_totals();
-	},
-
 	discount_percentage: function(doc, cdt, cdn) {
 		var item = frappe.get_doc(cdt, cdn);
 		item.discount_amount = 0.0;
@@ -239,7 +216,8 @@
 				child: item,
 				args: {
 					item_code: item.item_code,
-					warehouse: item.warehouse
+					warehouse: item.warehouse,
+					company: doc.company
 				}
 			});
 		}
diff --git a/erpnext/public/js/controllers/taxes_and_totals.js b/erpnext/public/js/controllers/taxes_and_totals.js
index d81321b..3a3ee38 100644
--- a/erpnext/public/js/controllers/taxes_and_totals.js
+++ b/erpnext/public/js/controllers/taxes_and_totals.js
@@ -158,16 +158,18 @@
 		let me = this;
 		frappe.flags.round_off_applicable_accounts = [];
 
-		return frappe.call({
-			"method": "erpnext.controllers.taxes_and_totals.get_round_off_applicable_accounts",
-			"args": {
-				"company": me.frm.doc.company,
-				"account_list": frappe.flags.round_off_applicable_accounts
-			},
-			callback: function(r) {
-				frappe.flags.round_off_applicable_accounts.push(...r.message);
-			}
-		});
+		if (me.frm.doc.company) {
+			return frappe.call({
+				"method": "erpnext.controllers.taxes_and_totals.get_round_off_applicable_accounts",
+				"args": {
+					"company": me.frm.doc.company,
+					"account_list": frappe.flags.round_off_applicable_accounts
+				},
+				callback: function(r) {
+					frappe.flags.round_off_applicable_accounts.push(...r.message);
+				}
+			});
+		}
 	},
 
 	determine_exclusive_rate: function() {
diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js
index e5f9049..1c0abdf 100644
--- a/erpnext/public/js/controllers/transaction.js
+++ b/erpnext/public/js/controllers/transaction.js
@@ -649,6 +649,40 @@
 		}
 	},
 
+	price_list_rate: function(doc, cdt, cdn) {
+		var item = frappe.get_doc(cdt, cdn);
+		frappe.model.round_floats_in(item, ["price_list_rate", "discount_percentage"]);
+
+		// check if child doctype is Sales Order Item/Qutation Item and calculate the rate
+		if (in_list(["Quotation Item", "Sales Order Item", "Delivery Note Item", "Sales Invoice Item", "POS Invoice Item", "Purchase Invoice Item", "Purchase Order Item", "Purchase Receipt Item"]), cdt)
+			this.apply_pricing_rule_on_item(item);
+		else
+			item.rate = flt(item.price_list_rate * (1 - item.discount_percentage / 100.0),
+				precision("rate", item));
+
+		this.calculate_taxes_and_totals();
+	},
+
+	margin_rate_or_amount: function(doc, cdt, cdn) {
+		// calculated the revised total margin and rate on margin rate changes
+		let item = frappe.get_doc(cdt, cdn);
+		this.apply_pricing_rule_on_item(item);
+		this.calculate_taxes_and_totals();
+		cur_frm.refresh_fields();
+	},
+
+	margin_type: function(doc, cdt, cdn) {
+		// calculate the revised total margin and rate on margin type changes
+		let item = frappe.get_doc(cdt, cdn);
+		if (!item.margin_type) {
+			frappe.model.set_value(cdt, cdn, "margin_rate_or_amount", 0);
+		} else {
+			this.apply_pricing_rule_on_item(item, doc, cdt, cdn);
+			this.calculate_taxes_and_totals();
+			cur_frm.refresh_fields();
+		}
+	},
+
 	get_incoming_rate: function(item, posting_date, posting_time, voucher_type, company) {
 
 		let item_args = {
@@ -1030,7 +1064,7 @@
 	},
 
 	set_margin_amount_based_on_currency: function(exchange_rate) {
-		if (in_list(["Quotation", "Sales Order", "Delivery Note", "Sales Invoice"]), this.frm.doc.doctype) {
+		if (in_list(["Quotation", "Sales Order", "Delivery Note", "Sales Invoice", "Purchase Invoice", "Purchase Order", "Purchase Receipt"]), this.frm.doc.doctype) {
 			var me = this;
 			$.each(this.frm.doc.items || [], function(i, d) {
 				if(d.margin_type == "Amount") {
@@ -1280,10 +1314,10 @@
 	change_grid_labels: function(company_currency) {
 		var me = this;
 
-		this.frm.set_currency_labels(["base_rate", "base_net_rate", "base_price_list_rate", "base_amount", "base_net_amount"],
+		this.frm.set_currency_labels(["base_rate", "base_net_rate", "base_price_list_rate", "base_amount", "base_net_amount", "base_rate_with_margin"],
 			company_currency, "items");
 
-		this.frm.set_currency_labels(["rate", "net_rate", "price_list_rate", "amount", "net_amount", "stock_uom_rate"],
+		this.frm.set_currency_labels(["rate", "net_rate", "price_list_rate", "amount", "net_amount", "stock_uom_rate", "rate_with_margin"],
 			this.frm.doc.currency, "items");
 
 		if(this.frm.fields_dict["operations"]) {
@@ -1321,7 +1355,7 @@
 
 		// toggle columns
 		var item_grid = this.frm.fields_dict["items"].grid;
-		$.each(["base_rate", "base_price_list_rate", "base_amount"], function(i, fname) {
+		$.each(["base_rate", "base_price_list_rate", "base_amount", "base_rate_with_margin"], function(i, fname) {
 			if(frappe.meta.get_docfield(item_grid.doctype, fname))
 				item_grid.set_column_disp(fname, me.frm.doc.currency != company_currency);
 		});
@@ -1468,7 +1502,7 @@
 				});
 
 				// if doctype is Quotation Item / Sales Order Iten then add Margin Type and rate in item_list
-				if (in_list(["Quotation Item", "Sales Order Item", "Delivery Note Item", "Sales Invoice Item"]), d.doctype){
+				if (in_list(["Quotation Item", "Sales Order Item", "Delivery Note Item", "Sales Invoice Item",  "Purchase Invoice Item", "Purchase Order Item", "Purchase Receipt Item"]), d.doctype) {
 					item_list[0]["margin_type"] = d.margin_type;
 					item_list[0]["margin_rate_or_amount"] = d.margin_rate_or_amount;
 				}
@@ -1885,7 +1919,6 @@
 			frappe.throw(__("Please enter Item Code to get batch no"));
 		} else if (doc.doctype == "Purchase Receipt" ||
 			(doc.doctype == "Purchase Invoice" && doc.update_stock)) {
-
 			return {
 				filters: {'item': item.item_code}
 			}
@@ -1911,9 +1944,8 @@
 	set_query_for_item_tax_template: function(doc, cdt, cdn) {
 		var item = frappe.get_doc(cdt, cdn);
 		if(!item.item_code) {
-			frappe.throw(__("Please enter Item Code to get item taxes"));
+			return doc.company ? {filters: {company: doc.company}} : {};
 		} else {
-
 			let filters = {
 				'item_code': item.item_code,
 				'valid_from': ["<=", doc.transaction_date || doc.bill_date || doc.posting_date],
@@ -2124,4 +2156,4 @@
 			}
 		}
 	});
-};
\ No newline at end of file
+};
diff --git a/erpnext/public/js/telephony.js b/erpnext/public/js/telephony.js
index b66126c..9548d6c 100644
--- a/erpnext/public/js/telephony.js
+++ b/erpnext/public/js/telephony.js
@@ -1,11 +1,18 @@
 frappe.ui.form.ControlData = frappe.ui.form.ControlData.extend( {
 	make_input() {
-		if (!this.df.read_only) {
-			this._super();
-		}
+		this._super();
 		if (this.df.options == 'Phone') {
 			this.setup_phone();
 		}
+		if (this.frm && this.frm.fields_dict) {
+			Object.values(this.frm.fields_dict).forEach(function(field) {
+				if (field.df.read_only === 1 && field.df.options === 'Phone' 
+					&& field.disp_area.style[0] != 'display' && !field.has_icon) {
+					field.setup_phone();
+					field.has_icon = true;
+				}
+			});
+		}
 	},
 	setup_phone() {
 		if (frappe.phone_call.handler) {
diff --git a/erpnext/public/js/utils.js b/erpnext/public/js/utils.js
index e5bd4d7..e5b50d8 100755
--- a/erpnext/public/js/utils.js
+++ b/erpnext/public/js/utils.js
@@ -595,21 +595,7 @@
 }
 
 erpnext.utils.map_current_doc = function(opts) {
-	let query_args = {};
-	if (opts.get_query_filters) {
-		query_args.filters = opts.get_query_filters;
-	}
-
-	if (opts.get_query_method) {
-		query_args.query = opts.get_query_method;
-	}
-
-	if (query_args.filters || query_args.query) {
-		opts.get_query = () => {
-			return query_args;
-		}
-	}
-	var _map = function() {
+	function _map() {
 		if($.isArray(cur_frm.doc.items) && cur_frm.doc.items.length > 0) {
 			// remove first item row if empty
 			if(!cur_frm.doc.items[0].item_code) {
@@ -683,8 +669,22 @@
 			}
 		});
 	}
-	if(opts.source_doctype) {
-		var d = new frappe.ui.form.MultiSelectDialog({
+
+	let query_args = {};
+	if (opts.get_query_filters) {
+		query_args.filters = opts.get_query_filters;
+	}
+
+	if (opts.get_query_method) {
+		query_args.query = opts.get_query_method;
+	}
+
+	if (query_args.filters || query_args.query) {
+		opts.get_query = () => query_args;
+	}
+
+	if (opts.source_doctype) {
+		const d = new frappe.ui.form.MultiSelectDialog({
 			doctype: opts.source_doctype,
 			target: opts.target,
 			date_field: opts.date_field || undefined,
@@ -703,7 +703,11 @@
 				_map();
 			},
 		});
-	} else if(opts.source_name) {
+
+		return d;
+	}
+
+	if (opts.source_name) {
 		opts.source_name = [opts.source_name];
 		_map();
 	}
diff --git a/erpnext/quality_management/doctype/quality_meeting/quality_meeting.json b/erpnext/quality_management/doctype/quality_meeting/quality_meeting.json
index ead403d..e2125c3 100644
--- a/erpnext/quality_management/doctype/quality_meeting/quality_meeting.json
+++ b/erpnext/quality_management/doctype/quality_meeting/quality_meeting.json
@@ -33,8 +33,7 @@
   },
   {
    "fieldname": "sb_00",
-   "fieldtype": "Section Break",
-   "label": "Agenda"
+   "fieldtype": "Section Break"
   },
   {
    "fieldname": "agenda",
@@ -44,13 +43,12 @@
   },
   {
    "fieldname": "sb_01",
-   "fieldtype": "Section Break",
-   "label": "Minutes"
+   "fieldtype": "Section Break"
   }
  ],
  "index_web_pages_for_search": 1,
  "links": [],
- "modified": "2020-10-27 16:36:45.657883",
+ "modified": "2021-02-27 16:36:45.657883",
  "modified_by": "Administrator",
  "module": "Quality Management",
  "name": "Quality Meeting",
@@ -85,4 +83,4 @@
  "sort_field": "modified",
  "sort_order": "DESC",
  "track_changes": 1
-}
\ No newline at end of file
+}
diff --git a/erpnext/non_profit/doctype/membership_settings/__init__.py b/erpnext/regional/doctype/tax_exemption_80g_certificate/__init__.py
similarity index 100%
copy from erpnext/non_profit/doctype/membership_settings/__init__.py
copy to erpnext/regional/doctype/tax_exemption_80g_certificate/__init__.py
diff --git a/erpnext/regional/doctype/tax_exemption_80g_certificate/tax_exemption_80g_certificate.js b/erpnext/regional/doctype/tax_exemption_80g_certificate/tax_exemption_80g_certificate.js
new file mode 100644
index 0000000..54cde9c
--- /dev/null
+++ b/erpnext/regional/doctype/tax_exemption_80g_certificate/tax_exemption_80g_certificate.js
@@ -0,0 +1,67 @@
+// Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+frappe.ui.form.on('Tax Exemption 80G Certificate', {
+	refresh: function(frm) {
+		if (frm.doc.donor) {
+			frm.set_query('donation', function() {
+				return {
+					filters: {
+						docstatus: 1,
+						donor: frm.doc.donor
+					}
+				};
+			});
+		}
+	},
+
+	recipient: function(frm) {
+		if (frm.doc.recipient === 'Donor') {
+			frm.set_value({
+				'member': '',
+				'member_name': '',
+				'member_email': '',
+				'member_pan_number': '',
+				'fiscal_year': '',
+				'total': 0,
+				'payments': []
+			});
+		} else {
+			frm.set_value({
+				'donor': '',
+				'donor_name': '',
+				'donor_email': '',
+				'donor_pan_number': '',
+				'donation': '',
+				'date_of_donation': '',
+				'amount': 0,
+				'mode_of_payment': '',
+				'razorpay_payment_id': ''
+			});
+		}
+	},
+
+	get_payments: function(frm) {
+		frm.call({
+			doc: frm.doc,
+			method: 'get_payments',
+			freeze: true
+		});
+	},
+
+	company: function(frm) {
+		if ((frm.doc.member || frm.doc.donor) && frm.doc.company) {
+			frm.call({
+				doc: frm.doc,
+				method: 'set_company_address',
+				freeze: true
+			});
+		}
+	},
+
+	donation: function(frm) {
+		if (frm.doc.recipient === 'Donor' && !frm.doc.donor) {
+			frappe.msgprint(__('Please select donor first'));
+		}
+	}
+});
diff --git a/erpnext/regional/doctype/tax_exemption_80g_certificate/tax_exemption_80g_certificate.json b/erpnext/regional/doctype/tax_exemption_80g_certificate/tax_exemption_80g_certificate.json
new file mode 100644
index 0000000..9eee722
--- /dev/null
+++ b/erpnext/regional/doctype/tax_exemption_80g_certificate/tax_exemption_80g_certificate.json
@@ -0,0 +1,297 @@
+{
+ "actions": [],
+ "autoname": "naming_series:",
+ "creation": "2021-02-15 12:37:21.577042",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "naming_series",
+  "recipient",
+  "member",
+  "member_name",
+  "member_email",
+  "member_pan_number",
+  "donor",
+  "donor_name",
+  "donor_email",
+  "donor_pan_number",
+  "column_break_4",
+  "date",
+  "fiscal_year",
+  "section_break_11",
+  "company",
+  "company_address",
+  "company_address_display",
+  "column_break_14",
+  "company_pan_number",
+  "company_80g_number",
+  "company_80g_wef",
+  "title",
+  "section_break_6",
+  "get_payments",
+  "payments",
+  "total",
+  "donation_details_section",
+  "donation",
+  "date_of_donation",
+  "amount",
+  "column_break_27",
+  "mode_of_payment",
+  "razorpay_payment_id"
+ ],
+ "fields": [
+  {
+   "fieldname": "recipient",
+   "fieldtype": "Select",
+   "in_list_view": 1,
+   "label": "Certificate Recipient",
+   "options": "Member\nDonor",
+   "reqd": 1
+  },
+  {
+   "depends_on": "eval:doc.recipient === \"Member\";",
+   "fieldname": "member",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "label": "Member",
+   "mandatory_depends_on": "eval:doc.recipient === \"Member\";",
+   "options": "Member"
+  },
+  {
+   "depends_on": "eval:doc.recipient === \"Member\";",
+   "fetch_from": "member.member_name",
+   "fieldname": "member_name",
+   "fieldtype": "Data",
+   "label": "Member Name",
+   "read_only": 1
+  },
+  {
+   "depends_on": "eval:doc.recipient === \"Donor\";",
+   "fieldname": "donor",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "label": "Donor",
+   "mandatory_depends_on": "eval:doc.recipient === \"Donor\";",
+   "options": "Donor"
+  },
+  {
+   "fieldname": "column_break_4",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "date",
+   "fieldtype": "Date",
+   "label": "Date",
+   "reqd": 1
+  },
+  {
+   "depends_on": "eval:doc.recipient === \"Member\";",
+   "fieldname": "section_break_6",
+   "fieldtype": "Section Break"
+  },
+  {
+   "fieldname": "payments",
+   "fieldtype": "Table",
+   "label": "Payments",
+   "options": "Tax Exemption 80G Certificate Detail"
+  },
+  {
+   "fieldname": "total",
+   "fieldtype": "Currency",
+   "in_list_view": 1,
+   "label": "Total",
+   "read_only": 1
+  },
+  {
+   "depends_on": "eval:doc.recipient === \"Member\";",
+   "fieldname": "fiscal_year",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "label": "Fiscal Year",
+   "options": "Fiscal Year"
+  },
+  {
+   "fieldname": "company",
+   "fieldtype": "Link",
+   "label": "Company",
+   "options": "Company",
+   "reqd": 1
+  },
+  {
+   "fieldname": "get_payments",
+   "fieldtype": "Button",
+   "label": "Get Memberships"
+  },
+  {
+   "fieldname": "naming_series",
+   "fieldtype": "Select",
+   "label": "Naming Series",
+   "options": "NPO-80G-.YYYY.-"
+  },
+  {
+   "fieldname": "section_break_11",
+   "fieldtype": "Section Break",
+   "label": "Company Details"
+  },
+  {
+   "fieldname": "company_address",
+   "fieldtype": "Link",
+   "label": "Company Address",
+   "options": "Address"
+  },
+  {
+   "fieldname": "column_break_14",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fetch_from": "company.pan_details",
+   "fieldname": "company_pan_number",
+   "fieldtype": "Data",
+   "label": "PAN Number",
+   "read_only": 1
+  },
+  {
+   "fieldname": "company_address_display",
+   "fieldtype": "Small Text",
+   "hidden": 1,
+   "label": "Company Address Display",
+   "print_hide": 1,
+   "read_only": 1
+  },
+  {
+   "fetch_from": "company.company_80g_number",
+   "fieldname": "company_80g_number",
+   "fieldtype": "Data",
+   "label": "80G Number",
+   "read_only": 1
+  },
+  {
+   "fetch_from": "company.with_effect_from",
+   "fieldname": "company_80g_wef",
+   "fieldtype": "Date",
+   "label": "80G With Effect From",
+   "read_only": 1
+  },
+  {
+   "depends_on": "eval:doc.recipient === \"Donor\";",
+   "fieldname": "donation_details_section",
+   "fieldtype": "Section Break",
+   "label": "Donation Details"
+  },
+  {
+   "fieldname": "donation",
+   "fieldtype": "Link",
+   "label": "Donation",
+   "mandatory_depends_on": "eval:doc.recipient === \"Donor\";",
+   "options": "Donation"
+  },
+  {
+   "fetch_from": "donation.amount",
+   "fieldname": "amount",
+   "fieldtype": "Currency",
+   "label": "Amount",
+   "read_only": 1
+  },
+  {
+   "fetch_from": "donation.mode_of_payment",
+   "fieldname": "mode_of_payment",
+   "fieldtype": "Link",
+   "label": "Mode of Payment",
+   "options": "Mode of Payment",
+   "read_only": 1
+  },
+  {
+   "fetch_from": "donation.razorpay_payment_id",
+   "fieldname": "razorpay_payment_id",
+   "fieldtype": "Data",
+   "label": "RazorPay Payment ID",
+   "read_only": 1
+  },
+  {
+   "fetch_from": "donation.date",
+   "fieldname": "date_of_donation",
+   "fieldtype": "Date",
+   "label": "Date of Donation",
+   "read_only": 1
+  },
+  {
+   "fieldname": "column_break_27",
+   "fieldtype": "Column Break"
+  },
+  {
+   "depends_on": "eval:doc.recipient === \"Donor\";",
+   "fetch_from": "donor.donor_name",
+   "fieldname": "donor_name",
+   "fieldtype": "Data",
+   "label": "Donor Name",
+   "read_only": 1
+  },
+  {
+   "depends_on": "eval:doc.recipient === \"Donor\";",
+   "fetch_from": "donor.email",
+   "fieldname": "donor_email",
+   "fieldtype": "Data",
+   "label": "Email",
+   "read_only": 1
+  },
+  {
+   "depends_on": "eval:doc.recipient === \"Member\";",
+   "fetch_from": "member.email_id",
+   "fieldname": "member_email",
+   "fieldtype": "Data",
+   "in_list_view": 1,
+   "label": "Email",
+   "read_only": 1
+  },
+  {
+   "depends_on": "eval:doc.recipient === \"Member\";",
+   "fetch_from": "member.pan_number",
+   "fieldname": "member_pan_number",
+   "fieldtype": "Data",
+   "label": "PAN Details",
+   "read_only": 1
+  },
+  {
+   "depends_on": "eval:doc.recipient === \"Donor\";",
+   "fetch_from": "donor.pan_number",
+   "fieldname": "donor_pan_number",
+   "fieldtype": "Data",
+   "label": "PAN Details",
+   "read_only": 1
+  },
+  {
+   "fieldname": "title",
+   "fieldtype": "Data",
+   "hidden": 1,
+   "label": "Title",
+   "print_hide": 1
+  }
+ ],
+ "index_web_pages_for_search": 1,
+ "links": [],
+ "modified": "2021-02-22 00:03:34.215633",
+ "modified_by": "Administrator",
+ "module": "Regional",
+ "name": "Tax Exemption 80G Certificate",
+ "owner": "Administrator",
+ "permissions": [
+  {
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "export": 1,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "System Manager",
+   "share": 1,
+   "write": 1
+  }
+ ],
+ "search_fields": "member, member_name",
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "title_field": "title",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/regional/doctype/tax_exemption_80g_certificate/tax_exemption_80g_certificate.py b/erpnext/regional/doctype/tax_exemption_80g_certificate/tax_exemption_80g_certificate.py
new file mode 100644
index 0000000..d734a18
--- /dev/null
+++ b/erpnext/regional/doctype/tax_exemption_80g_certificate/tax_exemption_80g_certificate.py
@@ -0,0 +1,89 @@
+# -*- 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 import _
+from frappe.model.document import Document
+from frappe.utils import getdate, flt, get_link_to_form
+from erpnext.accounts.utils import get_fiscal_year
+from frappe.contacts.doctype.address.address import get_company_address
+
+class TaxExemption80GCertificate(Document):
+	def validate(self):
+		self.validate_date()
+		self.validate_duplicates()
+		self.validate_company_details()
+		self.set_company_address()
+		self.set_title()
+
+	def validate_date(self):
+		if self.recipient == 'Member':
+			if getdate(self.date):
+				fiscal_year = get_fiscal_year(fiscal_year=self.fiscal_year, as_dict=True)
+
+				if not (fiscal_year.year_start_date <= getdate(self.date) \
+					<= fiscal_year.year_end_date):
+					frappe.throw(_('The Certificate Date is not in the Fiscal Year {0}').format(frappe.bold(self.fiscal_year)))
+
+	def validate_duplicates(self):
+		if self.recipient == 'Donor':
+			certificate = frappe.db.exists(self.doctype, {'donation': self.donation})
+			if certificate:
+				frappe.throw(_('An 80G Certificate {0} already exists for the donation {1}').format(
+					get_link_to_form(self.doctype, certificate), frappe.bold(self.donation)
+				), title=_('Duplicate Certificate'))
+
+	def validate_company_details(self):
+		fields = ['company_80g_number', 'with_effect_from', 'pan_details']
+		company_details = frappe.db.get_value('Company', self.company, fields, as_dict=True)
+		if not company_details.company_80g_number:
+			frappe.throw(_('Please set the {0} for company {1}').format(frappe.bold('80G Number'),
+				get_link_to_form('Company', self.company)))
+
+		if not company_details.pan_details:
+			frappe.throw(_('Please set the {0} for company {1}').format(frappe.bold('PAN Number'),
+				get_link_to_form('Company', self.company)))
+
+	def set_company_address(self):
+		address = get_company_address(self.company)
+		self.company_address = address.company_address
+		self.company_address_display = address.company_address_display
+
+	def set_title(self):
+		if self.recipient == "Member":
+			self.title = self.member_name
+		else:
+			self.title = self.donor_name
+
+	def get_payments(self):
+		if not self.member:
+			frappe.throw(_('Please select a Member first.'))
+
+		fiscal_year = get_fiscal_year(fiscal_year=self.fiscal_year, as_dict=True)
+
+		memberships = frappe.db.get_all('Membership', {
+			'member': self.member,
+			'from_date': ['between', (fiscal_year.year_start_date, fiscal_year.year_end_date)],
+			'to_date': ['between', (fiscal_year.year_start_date, fiscal_year.year_end_date)],
+			'membership_status': ('!=', 'Cancelled')
+		}, ['from_date', 'amount', 'name', 'invoice', 'payment_id'])
+
+		if not memberships:
+			frappe.msgprint(_('No Membership Payments found against the Member {0}').format(self.member))
+
+		total = 0
+		self.payments = []
+
+		for doc in memberships:
+			self.append('payments', {
+				'date': doc.from_date,
+				'amount': doc.amount,
+				'invoice_id': doc.invoice,
+				'razorpay_payment_id': doc.payment_id,
+				'membership': doc.name
+			})
+			total += flt(doc.amount)
+
+		self.total = total
diff --git a/erpnext/regional/doctype/tax_exemption_80g_certificate/test_tax_exemption_80g_certificate.py b/erpnext/regional/doctype/tax_exemption_80g_certificate/test_tax_exemption_80g_certificate.py
new file mode 100644
index 0000000..346ebbf
--- /dev/null
+++ b/erpnext/regional/doctype/tax_exemption_80g_certificate/test_tax_exemption_80g_certificate.py
@@ -0,0 +1,101 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors
+# See license.txt
+from __future__ import unicode_literals
+
+import frappe
+import unittest
+from frappe.utils import getdate
+from erpnext.accounts.utils import get_fiscal_year
+from erpnext.non_profit.doctype.donation.test_donation import create_donor, create_mode_of_payment, create_donor_type
+from erpnext.non_profit.doctype.donation.donation import create_donation
+from erpnext.non_profit.doctype.membership.test_membership import setup_membership, make_membership
+from erpnext.non_profit.doctype.member.member import create_member
+
+class TestTaxExemption80GCertificate(unittest.TestCase):
+	def setUp(self):
+		frappe.db.sql('delete from `tabTax Exemption 80G Certificate`')
+		frappe.db.sql('delete from `tabMembership`')
+		create_donor_type()
+		settings = frappe.get_doc('Non Profit Settings')
+		settings.company = '_Test Company'
+		settings.donation_company = '_Test Company'
+		settings.default_donor_type = '_Test Donor'
+		settings.creation_user = 'Administrator'
+		settings.save()
+
+		company = frappe.get_doc('Company', '_Test Company')
+		company.pan_details = 'BBBTI3374C'
+		company.company_80g_number = 'NQ.CIT(E)I2018-19/DEL-IE28615-27062018/10087'
+		company.with_effect_from = getdate()
+		company.save()
+
+	def test_duplicate_donation_certificate(self):
+		donor = create_donor()
+		create_mode_of_payment()
+		payment = frappe._dict({
+			'amount': 100,
+			'method': 'Debit Card',
+			'id': 'pay_MeXAmsgeKOhq7O'
+		})
+		donation = create_donation(donor, payment)
+
+		args = frappe._dict({
+			'recipient': 'Donor',
+			'donor': donor.name,
+			'donation': donation.name
+		})
+		certificate = create_80g_certificate(args)
+		certificate.insert()
+
+		# check company details
+		self.assertEquals(certificate.company_pan_number, 'BBBTI3374C')
+		self.assertEquals(certificate.company_80g_number, 'NQ.CIT(E)I2018-19/DEL-IE28615-27062018/10087')
+
+		# check donation details
+		self.assertEquals(certificate.amount, donation.amount)
+
+		duplicate_certificate = create_80g_certificate(args)
+		# duplicate validation
+		self.assertRaises(frappe.ValidationError, duplicate_certificate.insert)
+
+	def test_membership_80g_certificate(self):
+		plan = setup_membership()
+
+		# make test member
+		member_doc = create_member(frappe._dict({
+			'fullname': "_Test_Member",
+			'email': "_test_member_erpnext@example.com",
+			'plan_id': plan.name
+		}))
+		member_doc.make_customer_and_link()
+		member = member_doc.name
+
+		membership = make_membership(member, { "from_date": getdate() })
+		invoice = membership.generate_invoice(save=True)
+
+		args = frappe._dict({
+			'recipient': 'Member',
+			'member': member,
+			'fiscal_year': get_fiscal_year(getdate(), as_dict=True).get('name')
+		})
+		certificate = create_80g_certificate(args)
+		certificate.get_payments()
+		certificate.insert()
+
+		self.assertEquals(len(certificate.payments), 1)
+		self.assertEquals(certificate.payments[0].amount, membership.amount)
+		self.assertEquals(certificate.payments[0].invoice_id, invoice.name)
+
+
+def create_80g_certificate(args):
+	certificate = frappe.get_doc({
+		'doctype': 'Tax Exemption 80G Certificate',
+		'recipient': args.recipient,
+		'date': getdate(),
+		'company': '_Test Company'
+	})
+
+	certificate.update(args)
+
+	return certificate
\ No newline at end of file
diff --git a/erpnext/non_profit/doctype/membership_settings/__init__.py b/erpnext/regional/doctype/tax_exemption_80g_certificate_detail/__init__.py
similarity index 100%
copy from erpnext/non_profit/doctype/membership_settings/__init__.py
copy to erpnext/regional/doctype/tax_exemption_80g_certificate_detail/__init__.py
diff --git a/erpnext/regional/doctype/tax_exemption_80g_certificate_detail/tax_exemption_80g_certificate_detail.json b/erpnext/regional/doctype/tax_exemption_80g_certificate_detail/tax_exemption_80g_certificate_detail.json
new file mode 100644
index 0000000..dfa817d
--- /dev/null
+++ b/erpnext/regional/doctype/tax_exemption_80g_certificate_detail/tax_exemption_80g_certificate_detail.json
@@ -0,0 +1,66 @@
+{
+ "actions": [],
+ "creation": "2021-02-15 12:43:52.754124",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "date",
+  "amount",
+  "invoice_id",
+  "column_break_4",
+  "razorpay_payment_id",
+  "membership"
+ ],
+ "fields": [
+  {
+   "fieldname": "date",
+   "fieldtype": "Date",
+   "in_list_view": 1,
+   "label": "Date",
+   "reqd": 1
+  },
+  {
+   "fieldname": "amount",
+   "fieldtype": "Currency",
+   "in_list_view": 1,
+   "label": "Amount",
+   "reqd": 1
+  },
+  {
+   "fieldname": "invoice_id",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "label": "Invoice ID",
+   "options": "Sales Invoice",
+   "reqd": 1
+  },
+  {
+   "fieldname": "razorpay_payment_id",
+   "fieldtype": "Data",
+   "label": "Razorpay Payment ID"
+  },
+  {
+   "fieldname": "membership",
+   "fieldtype": "Link",
+   "label": "Membership",
+   "options": "Membership"
+  },
+  {
+   "fieldname": "column_break_4",
+   "fieldtype": "Column Break"
+  }
+ ],
+ "index_web_pages_for_search": 1,
+ "istable": 1,
+ "links": [],
+ "modified": "2021-02-15 16:35:10.777587",
+ "modified_by": "Administrator",
+ "module": "Regional",
+ "name": "Tax Exemption 80G Certificate Detail",
+ "owner": "Administrator",
+ "permissions": [],
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/regional/doctype/tax_exemption_80g_certificate_detail/tax_exemption_80g_certificate_detail.py b/erpnext/regional/doctype/tax_exemption_80g_certificate_detail/tax_exemption_80g_certificate_detail.py
new file mode 100644
index 0000000..bdad798
--- /dev/null
+++ b/erpnext/regional/doctype/tax_exemption_80g_certificate_detail/tax_exemption_80g_certificate_detail.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 TaxExemption80GCertificateDetail(Document):
+	pass
diff --git a/erpnext/regional/india/setup.py b/erpnext/regional/india/setup.py
index 5261984..ee49aae 100644
--- a/erpnext/regional/india/setup.py
+++ b/erpnext/regional/india/setup.py
@@ -21,6 +21,7 @@
 	add_permissions()
 	add_custom_roles_for_reports()
 	frappe.enqueue('erpnext.regional.india.setup.add_hsn_sac_codes', now=frappe.flags.in_test)
+	create_gratuity_rule()
 	add_print_formats()
 
 def add_hsn_sac_codes():
@@ -105,8 +106,9 @@
 	frappe.reload_doc("accounts", "print_format", "gst_pos_invoice")
 	frappe.reload_doc("accounts", "print_format", "GST E-Invoice")
 
-	frappe.db.sql(""" update `tabPrint Format` set disabled = 0 where
-		name in('GST POS Invoice', 'GST Tax Invoice', 'GST E-Invoice') """)
+	frappe.db.set_value("Print Format", "GST POS Invoice", "disabled", 0)
+	frappe.db.set_value("Print Format", "GST Tax Invoice", "disabled", 0)
+	frappe.db.set_value("Print Format", "GST E-Invoice", "disabled", 0)
 
 def make_custom_fields(update=True):
 	hsn_sac_field = dict(fieldname='gst_hsn_code', label='HSN/SAC',
@@ -398,9 +400,9 @@
 	si_einvoice_fields = [
 		dict(fieldname='irn', label='IRN', fieldtype='Data', read_only=1, insert_after='customer', no_copy=1, print_hide=1,
 			depends_on='eval:in_list(["Registered Regular", "SEZ", "Overseas", "Deemed Export"], doc.gst_category) && doc.irn_cancelled === 0'),
-		
+
 		dict(fieldname='ack_no', label='Ack. No.', fieldtype='Data', read_only=1, hidden=1, insert_after='irn', no_copy=1, print_hide=1),
-		
+
 		dict(fieldname='ack_date', label='Ack. Date', fieldtype='Data', read_only=1, hidden=1, insert_after='ack_no', no_copy=1, print_hide=1),
 
 		dict(fieldname='irn_cancelled', label='IRN Cancelled', fieldtype='Check', no_copy=1, print_hide=1,
@@ -498,6 +500,14 @@
 				fieldtype='Link', options='Salary Component', insert_after='basic_component'),
 			dict(fieldname='arrear_component', label='Arrear Component',
 				fieldtype='Link', options='Salary Component', insert_after='hra_component'),
+			dict(fieldname='non_profit_section', label='Non Profit Settings',
+				fieldtype='Section Break', insert_after='asset_received_but_not_billed', collapsible=1),
+			dict(fieldname='company_80g_number', label='80G Number',
+				fieldtype='Data', insert_after='non_profit_section'),
+			dict(fieldname='with_effect_from', label='80G With Effect From',
+				fieldtype='Date', insert_after='company_80g_number'),
+			dict(fieldname='pan_details', label='PAN Number',
+				fieldtype='Data', insert_after='with_effect_from')
 		],
 		'Employee Tax Exemption Declaration':[
 			dict(fieldname='hra_section', label='HRA Exemption',
@@ -580,7 +590,15 @@
 				'options': '\nWith Payment of Tax\nWithout Payment of Tax'
 			}
 		],
-		"Member": [
+		'Member': [
+			{
+				'fieldname': 'pan_number',
+				'label': 'PAN Details',
+				'fieldtype': 'Data',
+				'insert_after': 'email_id'
+			}
+		],
+		'Donor': [
 			{
 				'fieldname': 'pan_number',
 				'label': 'PAN Details',
@@ -642,7 +660,7 @@
 		pass
 
 	docs = get_tds_details(accounts, fiscal_year)
-	
+
 	for d in docs:
 		try:
 			doc = frappe.get_doc(d)
@@ -660,7 +678,7 @@
 				fy_exist = [k for k in doc.get('rates') if k.get('fiscal_year')==fiscal_year]
 				if not fy_exist:
 					doc.append("rates", d.get('rates')[0])
-					
+
 			doc.flags.ignore_permissions = True
 			doc.flags.ignore_mandatory = True
 			doc.save()
@@ -822,4 +840,24 @@
 			doctype="Tax Withholding Category", accounts=accounts,
 			rates=[{"fiscal_year": fiscal_year, "tax_withholding_rate": 20,
 			"single_threshold": 2500, "cumulative_threshold": 0}])
-	]
\ No newline at end of file
+	]
+
+def create_gratuity_rule():
+
+	# Standard Indain Gratuity Rule
+	if not frappe.db.exists("Gratuity Rule", "Indian Standard Gratuity Rule"):
+		rule = frappe.new_doc("Gratuity Rule")
+		rule.name = "Indian Standard Gratuity Rule"
+		rule.calculate_gratuity_amount_based_on = "Current Slab"
+		rule.work_experience_calculation_method = "Round Off Work Experience"
+		rule.minimum_year_for_gratuity = 5
+
+		fraction = 15/26
+		rule.append("gratuity_rule_slabs", {
+			"from_year": 0,
+			"to_year":0,
+			"fraction_of_applicable_earnings": fraction
+		})
+
+		rule.flags.ignore_mandatory = True
+		rule.save()
\ No newline at end of file
diff --git a/erpnext/regional/italy/setup.py b/erpnext/regional/italy/setup.py
index 217d623..95b92e7 100644
--- a/erpnext/regional/italy/setup.py
+++ b/erpnext/regional/italy/setup.py
@@ -189,9 +189,7 @@
 
 def setup_report():
 	report_name = 'Electronic Invoice Register'
-
-	frappe.db.sql(""" update `tabReport` set disabled = 0 where
-		name = %s """, report_name)
+	frappe.db.set_value("Report", report_name, "disabled", 0)
 
 	if not frappe.db.get_value('Custom Role', dict(report=report_name)):
 		frappe.get_doc(dict(
diff --git a/erpnext/regional/print_format/80g_certificate_for_donation/80g_certificate_for_donation.json b/erpnext/regional/print_format/80g_certificate_for_donation/80g_certificate_for_donation.json
new file mode 100644
index 0000000..a8da0bd
--- /dev/null
+++ b/erpnext/regional/print_format/80g_certificate_for_donation/80g_certificate_for_donation.json
@@ -0,0 +1,26 @@
+{
+ "absolute_value": 0,
+ "align_labels_right": 0,
+ "creation": "2021-02-22 00:17:33.878581",
+ "css": ".details {\n    font-size: 15px;\n    font-family: Tahoma, sans-serif;;\n    line-height: 150%;\n}\n\n.certificate-footer {\n    font-size: 15px;\n    font-family: Tahoma, sans-serif;\n    line-height: 140%;\n    margin-top: 120px;\n}\n\n.company-address {\n    color: #666666;\n    font-size: 15px;\n    font-family: Tahoma, sans-serif;;\n}",
+ "custom_format": 1,
+ "default_print_language": "en",
+ "disabled": 0,
+ "doc_type": "Tax Exemption 80G Certificate",
+ "docstatus": 0,
+ "doctype": "Print Format",
+ "font": "Default",
+ "html": "{% if letter_head and not no_letterhead -%}\n    <div class=\"letter-head\">{{ letter_head }}</div>\n{%- endif %}\n\n<div>\n    <h3 class=\"text-center\">{{ doc.company }} 80G Donor Certificate</h3>\n</div>\n<br><br>\n\n<div class=\"details\">\n    <p> <b>{{ _(\"Certificate No. : \") }}</b> {{ doc.name }} </p>\n    <p>\n    \t<b>{{ _(\"Date\") }} :</b> {{ doc.get_formatted(\"date\") }}<br>\n    </p>\n    <br><br>\n    \n    <div>\n\n        This is to confirm that the {{ doc.company }} received an amount of <b>{{doc.get_formatted(\"amount\")}}</b>\n        from <b>{{ doc.donor_name }}</b>\n        {% if doc.pan_number -%}\n            bearing PAN Number {{ doc.member_pan_number }}\n        {%- endif %}\n\n        via the Mode of Payment {{doc.mode_of_payment}}\n\n        {% if doc.razorpay_payment_id -%}\n            bearing RazorPay Payment ID {{ doc.razorpay_payment_id }}\n        {%- endif %}\n\n        on {{ doc.get_formatted(\"date_of_donation\") }}\n        <br><br>\n        \n        <p>\n            We thank you for your contribution towards the corpus of the {{ doc.company }} and helping support our work.\n        </p>\n\n    </div>\n</div>\n\n<br><br>\n<p class=\"company-address text-left\"> {{doc.company_address_display }}</p>\n\n<div class=\"certificate-footer text-center\">\n    <p><i>Computer generated receipt - Does not require signature</i></p><br>\n    \n    {% if doc.company_pan_number %}\n    <p>\n        <b>{{ doc.company }}'s PAN Account No :</b> {{ doc.company_pan_number }}\n    <p><br>\n    {% endif %}\n    \n    <p>\n        <b>80G Number : </b> {{ doc.company_80g_number }}\n        {% if doc.company_80g_wef %}\n            ( w.e.f. {{ doc.get_formatted('company_80g_wef') }} )\n        {% endif %}\n    </p><br>\n</div>",
+ "idx": 0,
+ "line_breaks": 0,
+ "modified": "2021-02-22 00:20:08.516600",
+ "modified_by": "Administrator",
+ "module": "Regional",
+ "name": "80G Certificate for Donation",
+ "owner": "Administrator",
+ "print_format_builder": 0,
+ "print_format_type": "Jinja",
+ "raw_printing": 0,
+ "show_section_headings": 0,
+ "standard": "Yes"
+}
\ No newline at end of file
diff --git a/erpnext/non_profit/doctype/membership_settings/__init__.py b/erpnext/regional/print_format/80g_certificate_for_donation/__init__.py
similarity index 100%
copy from erpnext/non_profit/doctype/membership_settings/__init__.py
copy to erpnext/regional/print_format/80g_certificate_for_donation/__init__.py
diff --git a/erpnext/regional/print_format/80g_certificate_for_membership/80g_certificate_for_membership.json b/erpnext/regional/print_format/80g_certificate_for_membership/80g_certificate_for_membership.json
new file mode 100644
index 0000000..f1b15aa
--- /dev/null
+++ b/erpnext/regional/print_format/80g_certificate_for_membership/80g_certificate_for_membership.json
@@ -0,0 +1,26 @@
+{
+ "absolute_value": 0,
+ "align_labels_right": 0,
+ "creation": "2021-02-15 16:53:55.026611",
+ "css": ".details {\n    font-size: 15px;\n    font-family: Tahoma, sans-serif;;\n    line-height: 150%;\n}\n\n.certificate-footer {\n    font-size: 15px;\n    font-family: Tahoma, sans-serif;\n    line-height: 140%;\n    margin-top: 120px;\n}\n\n.company-address {\n    color: #666666;\n    font-size: 15px;\n    font-family: Tahoma, sans-serif;;\n}",
+ "custom_format": 1,
+ "default_print_language": "en",
+ "disabled": 0,
+ "doc_type": "Tax Exemption 80G Certificate",
+ "docstatus": 0,
+ "doctype": "Print Format",
+ "font": "Default",
+ "html": "{% if letter_head and not no_letterhead -%}\n    <div class=\"letter-head\">{{ letter_head }}</div>\n{%- endif %}\n\n<div>\n    <h3 class=\"text-center\">{{ doc.company }} Members 80G Donor Certificate</h3>\n    <h3 class=\"text-center\">Financial Cycle {{ doc.fiscal_year }}</h3>\n</div>\n<br><br>\n\n<div class=\"details\">\n    <p> <b>{{ _(\"Certificate No. : \") }}</b> {{ doc.name }} </p>\n    <p>\n    \t<b>{{ _(\"Date\") }} :</b> {{ doc.get_formatted(\"date\") }}<br>\n    </p>\n    <br><br>\n    \n    <div>\n        This is to confirm that the {{ doc.company }} received a total amount of <b>{{doc.get_formatted(\"total\")}}</b>\n        from <b>{{ doc.member_name }}</b>\n        {% if doc.pan_number -%}\n            bearing PAN Number {{ doc.member_pan_number }}\n        {%- endif %}\n        as per the payment details given below:\n        \n        <br><br>\n        <table class=\"table table-bordered table-condensed\">\n        \t<thead>\n        \t\t<tr>\n        \t\t\t<th >{{ _(\"Date\") }}</th>\n        \t\t\t<th class=\"text-right\">{{ _(\"Amount\") }}</th>\n        \t\t\t<th class=\"text-right\">{{ _(\"Invoice ID\") }}</th>\n        \t\t</tr>\n        \t</thead>\n        \t<tbody>\n        \t\t{%- for payment in doc.payments -%}\n        \t\t<tr>\n        \t\t\t<td> {{ payment.date }} </td>\n        \t\t\t<td class=\"text-right\">{{ payment.get_formatted(\"amount\") }}</td>\n        \t\t\t<td class=\"text-right\">{{ payment.invoice_id }}</td>\n        \t\t</tr>\n        \t\t{%- endfor -%}\n        \t</tbody>\n        </table>\n        \n        <br>\n        \n        <p>\n            We thank you for your contribution towards the corpus of the {{ doc.company }} and helping support our work.\n        </p>\n\n    </div>\n</div>\n\n<br><br>\n<p class=\"company-address text-left\"> {{doc.company_address_display }}</p>\n\n<div class=\"certificate-footer text-center\">\n    <p><i>Computer generated receipt - Does not require signature</i></p><br>\n    \n    {% if doc.company_pan_number %}\n    <p>\n        <b>{{ doc.company }}'s PAN Account No :</b> {{ doc.company_pan_number }}\n    <p><br>\n    {% endif %}\n    \n    <p>\n        <b>80G Number : </b> {{ doc.company_80g_number }}\n        {% if doc.company_80g_wef %}\n            ( w.e.f. {{ doc.get_formatted('company_80g_wef') }} )\n        {% endif %}\n    </p><br>\n</div>",
+ "idx": 0,
+ "line_breaks": 0,
+ "modified": "2021-02-21 23:29:00.778973",
+ "modified_by": "Administrator",
+ "module": "Regional",
+ "name": "80G Certificate for Membership",
+ "owner": "Administrator",
+ "print_format_builder": 0,
+ "print_format_type": "Jinja",
+ "raw_printing": 0,
+ "show_section_headings": 0,
+ "standard": "Yes"
+}
\ No newline at end of file
diff --git a/erpnext/non_profit/doctype/membership_settings/__init__.py b/erpnext/regional/print_format/80g_certificate_for_membership/__init__.py
similarity index 100%
copy from erpnext/non_profit/doctype/membership_settings/__init__.py
copy to erpnext/regional/print_format/80g_certificate_for_membership/__init__.py
diff --git a/erpnext/regional/united_arab_emirates/setup.py b/erpnext/regional/united_arab_emirates/setup.py
index 776a82c..68208ab 100644
--- a/erpnext/regional/united_arab_emirates/setup.py
+++ b/erpnext/regional/united_arab_emirates/setup.py
@@ -7,12 +7,15 @@
 from frappe.custom.doctype.custom_field.custom_field import create_custom_fields
 from frappe.permissions import add_permission, update_permission_property
 from erpnext.setup.setup_wizard.operations.taxes_setup import create_sales_tax
+from erpnext.payroll.doctype.gratuity_rule.gratuity_rule import get_gratuity_rule
 
 def setup(company=None, patch=True):
 	make_custom_fields()
 	add_print_formats()
 	add_custom_roles_for_reports()
 	add_permissions()
+	create_gratuity_rule()
+
 	if company:
 		create_sales_tax(company)
 
@@ -155,3 +158,93 @@
 			add_permission(doctype, role, 0)
 			update_permission_property(doctype, role, 0, 'write', 1)
 			update_permission_property(doctype, role, 0, 'create', 1)
+
+def create_gratuity_rule():
+	rule_1 = rule_2 = rule_3 = None
+
+	# Rule Under Limited Contract
+	slabs = get_slab_for_limited_contract()
+	if not frappe.db.exists("Gratuity Rule", "Rule Under Limited Contract (UAE)"):
+		rule_1 = get_gratuity_rule("Rule Under Limited Contract (UAE)", slabs, calculate_gratuity_amount_based_on="Sum of all previous slabs")
+
+	# Rule Under Unlimited Contract on termination
+	slabs = get_slab_for_unlimited_contract_on_termination()
+	if not frappe.db.exists("Gratuity Rule", "Rule Under Unlimited Contract on termination (UAE)"):
+		rule_2 = get_gratuity_rule("Rule Under Unlimited Contract on termination (UAE)", slabs)
+
+	# Rule Under Unlimited Contract on resignation
+	slabs = get_slab_for_unlimited_contract_on_resignation()
+	if not frappe.db.exists("Gratuity Rule", "Rule Under Unlimited Contract on resignation (UAE)"):
+		rule_3 = get_gratuity_rule("Rule Under Unlimited Contract on resignation (UAE)", slabs)
+
+	#for applicable salary component user need to set this by its own
+	if rule_1:
+		rule_1.flags.ignore_mandatory = True
+		rule_1.save()
+	if rule_2:
+		rule_2.flags.ignore_mandatory = True
+		rule_2.save()
+	if rule_3:
+		rule_3.flags.ignore_mandatory = True
+		rule_3.save()
+
+
+def get_slab_for_limited_contract():
+	return [{
+		"from_year": 0,
+		"to_year":1,
+		"fraction_of_applicable_earnings": 0
+	},
+	{
+		"from_year": 1,
+		"to_year":5,
+		"fraction_of_applicable_earnings": 21/30
+	},
+	{
+		"from_year": 5,
+		"to_year":0,
+		"fraction_of_applicable_earnings": 1
+	}]
+
+def get_slab_for_unlimited_contract_on_termination():
+	return [{
+		"from_year": 0,
+		"to_year":1,
+		"fraction_of_applicable_earnings": 0
+	},
+	{
+		"from_year": 1,
+		"to_year":5,
+		"fraction_of_applicable_earnings": 21/30
+	},
+	{
+		"from_year": 5,
+		"to_year":0,
+		"fraction_of_applicable_earnings": 1
+	}]
+
+def get_slab_for_unlimited_contract_on_resignation():
+	fraction_1 = 1/3 * 21/30
+	fraction_2 = 2/3 * 21/30
+	fraction_3 = 21/30
+
+	return [{
+		"from_year": 0,
+		"to_year":1,
+		"fraction_of_applicable_earnings": 0
+	},
+	{
+		"from_year": 1,
+		"to_year":3,
+		"fraction_of_applicable_earnings": fraction_1
+	},
+	{
+		"from_year": 3,
+		"to_year":5,
+		"fraction_of_applicable_earnings": fraction_2
+	},
+	{
+		"from_year": 5,
+		"to_year":0,
+		"fraction_of_applicable_earnings": fraction_3
+	}]
diff --git a/erpnext/regional/united_states/setup.py b/erpnext/regional/united_states/setup.py
index 2b0ecaf..24ab1cf 100644
--- a/erpnext/regional/united_states/setup.py
+++ b/erpnext/regional/united_states/setup.py
@@ -36,5 +36,4 @@
 
 def add_print_formats():
 	frappe.reload_doc("regional", "print_format", "irs_1099_form")
-	frappe.db.sql(""" update `tabPrint Format` set disabled = 0 where
-		name in('IRS 1099 Form') """)
+	frappe.db.set_value("Print Format", "IRS 1099 Form", "disabled", 0)
diff --git a/erpnext/selling/doctype/customer/test_customer.py b/erpnext/selling/doctype/customer/test_customer.py
index 87fdaa3..7761aa7 100644
--- a/erpnext/selling/doctype/customer/test_customer.py
+++ b/erpnext/selling/doctype/customer/test_customer.py
@@ -54,7 +54,11 @@
 		details = get_party_details("_Test Customer")
 
 		for key, value in iteritems(to_check):
-			self.assertEqual(value, details.get(key))
+			val = details.get(key)
+			if not val and not isinstance(val, list):
+				val = None
+
+			self.assertEqual(value, val)
 
 	def test_party_details_tax_category(self):
 		from erpnext.accounts.party import get_party_details
diff --git a/erpnext/selling/doctype/quotation_item/quotation_item.json b/erpnext/selling/doctype/quotation_item/quotation_item.json
index a6785f7..8b53902 100644
--- a/erpnext/selling/doctype/quotation_item/quotation_item.json
+++ b/erpnext/selling/doctype/quotation_item/quotation_item.json
@@ -641,6 +641,7 @@
    "fieldname": "stock_uom_rate",
    "fieldtype": "Currency",
    "label": "Rate of Stock UOM",
+   "no_copy": 1,
    "options": "currency",
    "read_only": 1
   }
@@ -648,7 +649,7 @@
  "idx": 1,
  "istable": 1,
  "links": [],
- "modified": "2021-01-30 21:39:40.174551",
+ "modified": "2021-02-23 01:13:54.670763",
  "modified_by": "Administrator",
  "module": "Selling",
  "name": "Quotation Item",
diff --git a/erpnext/selling/doctype/sales_order/test_sales_order.py b/erpnext/selling/doctype/sales_order/test_sales_order.py
index 52a0174..ee16f44 100644
--- a/erpnext/selling/doctype/sales_order/test_sales_order.py
+++ b/erpnext/selling/doctype/sales_order/test_sales_order.py
@@ -555,12 +555,12 @@
 		new_item_with_tax = frappe.get_doc("Item", "Test Item with Tax")
 
 		new_item_with_tax.append("taxes", {
-			"item_tax_template": "Test Update Items Template",
+			"item_tax_template": "Test Update Items Template - _TC",
 			"valid_from": nowdate()
 		})
 		new_item_with_tax.save()
 
-		tax_template = "_Test Account Excise Duty @ 10"
+		tax_template = "_Test Account Excise Duty @ 10 - _TC"
 		item =  "_Test Item Home Desktop 100"
 		if not frappe.db.exists("Item Tax", {"parent":item, "item_tax_template":tax_template}):
 			item_doc = frappe.get_doc("Item", item)
@@ -614,7 +614,7 @@
 		so.cancel()
 		so.delete()
 		new_item_with_tax.delete()
-		frappe.get_doc("Item Tax Template", "Test Update Items Template").delete()
+		frappe.get_doc("Item Tax Template", "Test Update Items Template - _TC").delete()
 		frappe.db.set_value("Stock Settings", None, "default_warehouse", old_stock_settings_value)
 
 	def test_warehouse_user(self):
diff --git a/erpnext/selling/doctype/sales_order_item/sales_order_item.json b/erpnext/selling/doctype/sales_order_item/sales_order_item.json
index 37e47a9..1e5590e 100644
--- a/erpnext/selling/doctype/sales_order_item/sales_order_item.json
+++ b/erpnext/selling/doctype/sales_order_item/sales_order_item.json
@@ -786,6 +786,7 @@
    "fieldname": "stock_uom_rate",
    "fieldtype": "Currency",
    "label": "Rate of Stock UOM",
+   "no_copy": 1,
    "options": "currency",
    "read_only": 1
   }
@@ -793,7 +794,7 @@
  "idx": 1,
  "istable": 1,
  "links": [],
- "modified": "2021-01-30 21:35:07.617320",
+ "modified": "2021-02-23 01:15:05.803091",
  "modified_by": "Administrator",
  "module": "Selling",
  "name": "Sales Order Item",
diff --git a/erpnext/selling/sales_common.js b/erpnext/selling/sales_common.js
index ce08464..0428573 100644
--- a/erpnext/selling/sales_common.js
+++ b/erpnext/selling/sales_common.js
@@ -127,20 +127,6 @@
 		this.set_dynamic_labels();
 	},
 
-	price_list_rate: function(doc, cdt, cdn) {
-		var item = frappe.get_doc(cdt, cdn);
-		frappe.model.round_floats_in(item, ["price_list_rate", "discount_percentage"]);
-
-		// check if child doctype is Sales Order Item/Qutation Item and calculate the rate
-		if(in_list(["Quotation Item", "Sales Order Item", "Delivery Note Item", "Sales Invoice Item", "POS Invoice Item"]), cdt)
-			this.apply_pricing_rule_on_item(item);
-		else
-			item.rate = flt(item.price_list_rate * (1 - item.discount_percentage / 100.0),
-				precision("rate", item));
-
-		this.calculate_taxes_and_totals();
-	},
-
 	discount_percentage: function(doc, cdt, cdn) {
 		var item = frappe.get_doc(cdt, cdn);
 		item.discount_amount = 0.0;
@@ -353,26 +339,6 @@
 		refresh_field('product_bundle_help');
 	},
 
-	margin_rate_or_amount: function(doc, cdt, cdn) {
-		// calculated the revised total margin and rate on margin rate changes
-		var item = locals[cdt][cdn];
-		this.apply_pricing_rule_on_item(item)
-		this.calculate_taxes_and_totals();
-		cur_frm.refresh_fields();
-	},
-
-	margin_type: function(doc, cdt, cdn){
-		// calculate the revised total margin and rate on margin type changes
-		var item = locals[cdt][cdn];
-		if(!item.margin_type) {
-			frappe.model.set_value(cdt, cdn, "margin_rate_or_amount", 0);
-		} else {
-			this.apply_pricing_rule_on_item(item, doc,cdt, cdn)
-			this.calculate_taxes_and_totals();
-			cur_frm.refresh_fields();
-		}
-	},
-
 	company_address: function() {
 		var me = this;
 		if(this.frm.doc.company_address) {
diff --git a/erpnext/setup/doctype/company/company.json b/erpnext/setup/doctype/company/company.json
index d49ae7c..56f60df 100644
--- a/erpnext/setup/doctype/company/company.json
+++ b/erpnext/setup/doctype/company/company.json
@@ -725,7 +725,7 @@
   {
    "fieldname": "default_in_transit_warehouse",
    "fieldtype": "Link",
-   "label": "Default In Transit Warehouse",
+   "label": "Default In-Transit Warehouse",
    "options": "Warehouse"
   },
   {
@@ -740,7 +740,7 @@
  "image_field": "company_logo",
  "is_tree": 1,
  "links": [],
- "modified": "2020-12-03 12:27:27.085094",
+ "modified": "2021-02-16 15:53:37.167589",
  "modified_by": "Administrator",
  "module": "Setup",
  "name": "Company",
diff --git a/erpnext/setup/doctype/company/company.py b/erpnext/setup/doctype/company/company.py
index 819ba78..433851c 100644
--- a/erpnext/setup/doctype/company/company.py
+++ b/erpnext/setup/doctype/company/company.py
@@ -390,8 +390,10 @@
 		frappe.db.sql("delete from tabDepartment where company=%s", self.name)
 		frappe.db.sql("delete from `tabTax Withholding Account` where company=%s", self.name)
 
+		# delete tax templates
 		frappe.db.sql("delete from `tabSales Taxes and Charges Template` where company=%s", self.name)
 		frappe.db.sql("delete from `tabPurchase Taxes and Charges Template` where company=%s", self.name)
+		frappe.db.sql("delete from `tabItem Tax Template` where company=%s", self.name)
 
 @frappe.whitelist()
 def enqueue_replace_abbr(company, old, new):
diff --git a/erpnext/setup/doctype/company/company_list.js b/erpnext/setup/doctype/company/company_list.js
index 0172865..1d1184f 100644
--- a/erpnext/setup/doctype/company/company_list.js
+++ b/erpnext/setup/doctype/company/company_list.js
@@ -1,10 +1,5 @@
 frappe.listview_settings['Company'] = {
-    onload: () => {
-        frappe.breadcrumbs.add({
-            type: 'Custom',
-            module: __('Accounts'),
-            label: __('Accounts'),
-            route: '#modules/Accounts'
-        });
-    }
-}
\ No newline at end of file
+	onload() {
+		frappe.breadcrumbs.add('Accounts');
+	},
+};
diff --git a/erpnext/setup/doctype/item_group/test_records.json b/erpnext/setup/doctype/item_group/test_records.json
index 7115964..146da87 100644
--- a/erpnext/setup/doctype/item_group/test_records.json
+++ b/erpnext/setup/doctype/item_group/test_records.json
@@ -79,13 +79,13 @@
    {
     "doctype": "Item Tax",
     "parentfield": "taxes",
-    "item_tax_template": "_Test Account Excise Duty @ 10",
+    "item_tax_template": "_Test Account Excise Duty @ 10 - _TC",
     "tax_category": ""
    },
    {
     "doctype": "Item Tax",
     "parentfield": "taxes",
-    "item_tax_template": "_Test Account Excise Duty @ 12",
+    "item_tax_template": "_Test Account Excise Duty @ 12 - _TC",
     "tax_category": "_Test Tax Category 1"
    }
   ]
@@ -99,7 +99,7 @@
    {
     "doctype": "Item Tax",
     "parentfield": "taxes",
-    "item_tax_template": "_Test Account Excise Duty @ 15",
+    "item_tax_template": "_Test Account Excise Duty @ 15 - _TC",
     "tax_category": ""
    }
   ]
diff --git a/erpnext/setup/setup_wizard/operations/install_fixtures.py b/erpnext/setup/setup_wizard/operations/install_fixtures.py
index 72ed002..5053c6a 100644
--- a/erpnext/setup/setup_wizard/operations/install_fixtures.py
+++ b/erpnext/setup/setup_wizard/operations/install_fixtures.py
@@ -195,6 +195,7 @@
 		{'doctype': "Party Type", "party_type": "Member", "account_type": "Receivable"},
 		{'doctype': "Party Type", "party_type": "Shareholder", "account_type": "Payable"},
 		{'doctype': "Party Type", "party_type": "Student", "account_type": "Receivable"},
+		{'doctype': "Party Type", "party_type": "Donor", "account_type": "Receivable"},
 
 		{'doctype': "Opportunity Type", "name": "Hub"},
 		{'doctype': "Opportunity Type", "name": _("Sales")},
diff --git a/erpnext/stock/doctype/delivery_note_item/delivery_note_item.json b/erpnext/stock/doctype/delivery_note_item/delivery_note_item.json
index 1799624..b05090a 100644
--- a/erpnext/stock/doctype/delivery_note_item/delivery_note_item.json
+++ b/erpnext/stock/doctype/delivery_note_item/delivery_note_item.json
@@ -750,6 +750,7 @@
    "fieldname": "stock_uom_rate",
    "fieldtype": "Currency",
    "label": "Rate of Stock UOM",
+   "no_copy": 1,
    "options": "currency",
    "read_only": 1
   }
@@ -758,7 +759,7 @@
  "index_web_pages_for_search": 1,
  "istable": 1,
  "links": [],
- "modified": "2021-01-30 21:42:03.767968",
+ "modified": "2021-02-23 01:04:08.588104",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Delivery Note Item",
diff --git a/erpnext/stock/doctype/item/item.js b/erpnext/stock/doctype/item/item.js
index f851aaf..5539123 100644
--- a/erpnext/stock/doctype/item/item.js
+++ b/erpnext/stock/doctype/item/item.js
@@ -85,7 +85,7 @@
 		}
 		if (frm.doc.variant_of) {
 			frm.set_intro(__('This Item is a Variant of {0} (Template).',
-				[`<a href="/app/item/${frm.doc.variant_of}">${frm.doc.variant_of}</a>`]), true);
+				[`<a href="/app/item/${frm.doc.variant_of}" onclick="location.reload()">${frm.doc.variant_of}</a>`]), true);
 		}
 
 		if (frappe.defaults.get_default("item_naming_by")!="Naming Series" || frm.doc.variant_of) {
diff --git a/erpnext/stock/doctype/item/test_item.py b/erpnext/stock/doctype/item/test_item.py
index 109731a..36d0de1 100644
--- a/erpnext/stock/doctype/item/test_item.py
+++ b/erpnext/stock/doctype/item/test_item.py
@@ -104,41 +104,41 @@
 	def test_item_tax_template(self):
 		expected_item_tax_template = [
 			{"item_code": "_Test Item With Item Tax Template", "tax_category": "",
-				"item_tax_template": "_Test Account Excise Duty @ 10"},
+				"item_tax_template": "_Test Account Excise Duty @ 10 - _TC"},
 			{"item_code": "_Test Item With Item Tax Template", "tax_category": "_Test Tax Category 1",
-				"item_tax_template": "_Test Account Excise Duty @ 12"},
+				"item_tax_template": "_Test Account Excise Duty @ 12 - _TC"},
 			{"item_code": "_Test Item With Item Tax Template", "tax_category": "_Test Tax Category 2",
 				"item_tax_template": None},
 
 			{"item_code": "_Test Item Inherit Group Item Tax Template 1", "tax_category": "",
-				"item_tax_template": "_Test Account Excise Duty @ 10"},
+				"item_tax_template": "_Test Account Excise Duty @ 10 - _TC"},
 			{"item_code": "_Test Item Inherit Group Item Tax Template 1", "tax_category": "_Test Tax Category 1",
-				"item_tax_template": "_Test Account Excise Duty @ 12"},
+				"item_tax_template": "_Test Account Excise Duty @ 12 - _TC"},
 			{"item_code": "_Test Item Inherit Group Item Tax Template 1", "tax_category": "_Test Tax Category 2",
 				"item_tax_template": None},
 
 			{"item_code": "_Test Item Inherit Group Item Tax Template 2", "tax_category": "",
-				"item_tax_template": "_Test Account Excise Duty @ 15"},
+				"item_tax_template": "_Test Account Excise Duty @ 15 - _TC"},
 			{"item_code": "_Test Item Inherit Group Item Tax Template 2", "tax_category": "_Test Tax Category 1",
-				"item_tax_template": "_Test Account Excise Duty @ 12"},
+				"item_tax_template": "_Test Account Excise Duty @ 12 - _TC"},
 			{"item_code": "_Test Item Inherit Group Item Tax Template 2", "tax_category": "_Test Tax Category 2",
 				"item_tax_template": None},
 
 			{"item_code": "_Test Item Override Group Item Tax Template", "tax_category": "",
-				"item_tax_template": "_Test Account Excise Duty @ 20"},
+				"item_tax_template": "_Test Account Excise Duty @ 20 - _TC"},
 			{"item_code": "_Test Item Override Group Item Tax Template", "tax_category": "_Test Tax Category 1",
-				"item_tax_template": "_Test Item Tax Template 1"},
+				"item_tax_template": "_Test Item Tax Template 1 - _TC"},
 			{"item_code": "_Test Item Override Group Item Tax Template", "tax_category": "_Test Tax Category 2",
 				"item_tax_template": None},
 		]
 
 		expected_item_tax_map = {
 			None: {},
-			"_Test Account Excise Duty @ 10": {"_Test Account Excise Duty - _TC": 10},
-			"_Test Account Excise Duty @ 12": {"_Test Account Excise Duty - _TC": 12},
-			"_Test Account Excise Duty @ 15": {"_Test Account Excise Duty - _TC": 15},
-			"_Test Account Excise Duty @ 20": {"_Test Account Excise Duty - _TC": 20},
-			"_Test Item Tax Template 1": {"_Test Account Excise Duty - _TC": 5, "_Test Account Education Cess - _TC": 10,
+			"_Test Account Excise Duty @ 10 - _TC": {"_Test Account Excise Duty - _TC": 10},
+			"_Test Account Excise Duty @ 12 - _TC": {"_Test Account Excise Duty - _TC": 12},
+			"_Test Account Excise Duty @ 15 - _TC": {"_Test Account Excise Duty - _TC": 15},
+			"_Test Account Excise Duty @ 20 - _TC": {"_Test Account Excise Duty - _TC": 20},
+			"_Test Item Tax Template 1 - _TC": {"_Test Account Excise Duty - _TC": 5, "_Test Account Education Cess - _TC": 10,
 				"_Test Account S&H Education Cess - _TC": 15}
 		}
 
diff --git a/erpnext/stock/doctype/item/test_records.json b/erpnext/stock/doctype/item/test_records.json
index 8f437b1..909c4ee 100644
--- a/erpnext/stock/doctype/item/test_records.json
+++ b/erpnext/stock/doctype/item/test_records.json
@@ -92,7 +92,7 @@
    {
     "doctype": "Item Tax",
     "parentfield": "taxes",
-    "item_tax_template": "_Test Account Excise Duty @ 10"
+    "item_tax_template": "_Test Account Excise Duty @ 10 - _TC"
    }
   ],
   "stock_uom": "_Test UOM 1"
@@ -370,12 +370,12 @@
    {
     "doctype": "Item Tax",
     "parentfield": "taxes",
-    "item_tax_template": "_Test Account Excise Duty @ 10"
+    "item_tax_template": "_Test Account Excise Duty @ 10 - _TC"
    },
    {
     "doctype": "Item Tax",
     "parentfield": "taxes",
-    "item_tax_template": "_Test Account Excise Duty @ 12",
+    "item_tax_template": "_Test Account Excise Duty @ 12 - _TC",
     "tax_category": "_Test Tax Category 1"
    }
   ]
@@ -449,13 +449,13 @@
    {
     "doctype": "Item Tax",
     "parentfield": "taxes",
-    "item_tax_template": "_Test Account Excise Duty @ 20"
+    "item_tax_template": "_Test Account Excise Duty @ 20 - _TC"
    },
    {
     "doctype": "Item Tax",
     "parentfield": "taxes",
     "tax_category": "_Test Tax Category 1",
-    "item_tax_template": "_Test Item Tax Template 1"
+    "item_tax_template": "_Test Item Tax Template 1 - _TC"
    }
   ]
  },
diff --git a/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json b/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json
index 8974ad9..efe3642 100644
--- a/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json
+++ b/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json
@@ -37,10 +37,16 @@
   "returned_qty",
   "rate_and_amount",
   "price_list_rate",
-  "discount_percentage",
-  "discount_amount",
   "col_break3",
   "base_price_list_rate",
+  "discount_and_margin_section",
+  "margin_type",
+  "margin_rate_or_amount",
+  "rate_with_margin",
+  "column_break_37",
+  "discount_percentage",
+  "discount_amount",
+  "base_rate_with_margin",
   "sec_break1",
   "rate",
   "amount",
@@ -880,6 +886,7 @@
    "fieldname": "stock_uom_rate",
    "fieldtype": "Currency",
    "label": "Rate of Stock UOM",
+   "no_copy": 1,
    "options": "currency",
    "read_only": 1
   },
@@ -890,12 +897,55 @@
    "no_copy": 1,
    "print_hide": 1,
    "read_only": 1
+  },
+  {
+   "collapsible": 1,
+   "fieldname": "discount_and_margin_section",
+   "fieldtype": "Section Break",
+   "label": "Discount and Margin"
+  },
+  {
+   "depends_on": "price_list_rate",
+   "fieldname": "margin_type",
+   "fieldtype": "Select",
+   "label": "Margin Type",
+   "options": "\nPercentage\nAmount",
+   "print_hide": 1
+  },
+  {
+   "depends_on": "eval:doc.margin_type && doc.price_list_rate",
+   "fieldname": "margin_rate_or_amount",
+   "fieldtype": "Float",
+   "label": "Margin Rate or Amount",
+   "print_hide": 1
+  },
+  {
+   "depends_on": "eval:doc.margin_type && doc.price_list_rate && doc.margin_rate_or_amount",
+   "fieldname": "rate_with_margin",
+   "fieldtype": "Currency",
+   "label": "Rate With Margin",
+   "options": "currency",
+   "print_hide": 1,
+   "read_only": 1
+  },
+  {
+   "fieldname": "column_break_37",
+   "fieldtype": "Column Break"
+  },
+  {
+   "depends_on": "eval:doc.margin_type && doc.price_list_rate && doc.margin_rate_or_amount",
+   "fieldname": "base_rate_with_margin",
+   "fieldtype": "Currency",
+   "label": "Rate With Margin (Company Currency)",
+   "options": "Company:company:default_currency",
+   "print_hide": 1,
+   "read_only": 1
   }
  ],
  "idx": 1,
  "istable": 1,
  "links": [],
- "modified": "2021-01-30 21:44:06.918515",
+ "modified": "2021-02-23 00:59:14.360847",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Purchase Receipt Item",
diff --git a/erpnext/stock/doctype/serial_no/serial_no.py b/erpnext/stock/doctype/serial_no/serial_no.py
index 6bacf1f..c8d8ca9 100644
--- a/erpnext/stock/doctype/serial_no/serial_no.py
+++ b/erpnext/stock/doctype/serial_no/serial_no.py
@@ -554,7 +554,7 @@
 
 	if batch_nos:
 		try:
-			filters["batch_no"] = json.loads(batch_nos)
+			filters["batch_no"] = json.loads(batch_nos) if (type(json.loads(batch_nos)) == list) else [json.loads(batch_nos)]
 		except:
 			filters["batch_no"] = [batch_nos]
 
@@ -626,4 +626,4 @@
 				batch_no_condition=batch_no_condition
 			), filters, as_dict=1)
 
-	return serial_numbers
\ No newline at end of file
+	return serial_numbers
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.js b/erpnext/stock/doctype/stock_entry/stock_entry.js
index 726118d..64dcbed 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.js
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.js
@@ -231,15 +231,37 @@
 			}, __("Get Items From"));
 
 			frm.add_custom_button(__('Material Request'), function() {
-				erpnext.utils.map_current_doc({
+				const allowed_request_types = ["Material Transfer", "Material Issue", "Customer Provided"];
+				const depends_on_condition = "eval:doc.material_request_type==='Customer Provided'";
+				const d = erpnext.utils.map_current_doc({
 					method: "erpnext.stock.doctype.material_request.material_request.make_stock_entry",
 					source_doctype: "Material Request",
 					target: frm,
 					date_field: "schedule_date",
-					setters: {},
+					setters: [{
+						fieldtype: 'Select',
+						label: __('Purpose'),
+						options: allowed_request_types.join("\n"),
+						fieldname: 'material_request_type',
+						default: "Material Transfer",
+						mandatory: 1,
+						change() {
+							if (this.value === 'Customer Provided') {
+								d.dialog.get_field("customer").set_focus();
+							}
+						},
+					},
+					{
+						fieldtype: 'Link',
+						label: __('Customer'),
+						options: 'Customer',
+						fieldname: 'customer',
+						depends_on: depends_on_condition,
+						mandatory_depends_on: depends_on_condition,
+					}],
 					get_query_filters: {
 						docstatus: 1,
-						material_request_type: ["in", ["Material Transfer", "Material Issue"]],
+						material_request_type: ["in", allowed_request_types],
 						status: ["not in", ["Transferred", "Issued"]]
 					}
 				})
@@ -569,6 +591,7 @@
 
 	add_to_transit: function(frm) {
 		if(frm.doc.add_to_transit && frm.doc.purpose=='Material Transfer') {
+			frm.set_value('to_warehouse', '');
 			frm.set_value('stock_entry_type', 'Material Transfer');
 			frm.fields_dict.to_warehouse.get_query = function() {
 				return {
@@ -579,7 +602,15 @@
 					}
 				};
 			};
-			frappe.db.get_value('Company', frm.doc.company, 'default_in_transit_warehouse', (r) => {
+			frm.trigger('set_tansit_warehouse');
+		}
+	},
+
+	set_tansit_warehouse: function(frm) {
+		if(frm.doc.add_to_transit && frm.doc.purpose == 'Material Transfer' && !frm.doc.to_warehouse) {
+			let dt = frm.doc.from_warehouse ? 'Warehouse' : 'Company';
+			let dn = frm.doc.from_warehouse ? frm.doc.from_warehouse : frm.doc.company;
+			frappe.db.get_value(dt, dn, 'default_in_transit_warehouse', (r) => {
 				if (r.default_in_transit_warehouse) {
 					frm.set_value('to_warehouse', r.default_in_transit_warehouse);
 				}
@@ -946,6 +977,7 @@
 	},
 
 	from_warehouse: function(doc) {
+		this.frm.trigger('set_tansit_warehouse');
 		this.set_warehouse_in_children(doc.items, "s_warehouse", doc.from_warehouse);
 	},
 
diff --git a/erpnext/stock/doctype/warehouse/warehouse.js b/erpnext/stock/doctype/warehouse/warehouse.js
index 1bea00e..1f17250 100644
--- a/erpnext/stock/doctype/warehouse/warehouse.js
+++ b/erpnext/stock/doctype/warehouse/warehouse.js
@@ -3,6 +3,18 @@
 
 
 frappe.ui.form.on("Warehouse", {
+	onload: function(frm) {
+		frm.set_query("default_in_transit_warehouse", function() {
+			return {
+				filters:{
+					'warehouse_type' : 'Transit',
+					'is_group': 0,
+					'company': frm.doc.company
+				}
+			};
+		});
+	},
+
 	refresh: function(frm) {
 		frm.toggle_display('warehouse_name', frm.doc.__islocal);
 		frm.toggle_display(['address_html','contact_html'], !frm.doc.__islocal);
diff --git a/erpnext/stock/doctype/warehouse/warehouse.json b/erpnext/stock/doctype/warehouse/warehouse.json
index 1cc600b..bddb114 100644
--- a/erpnext/stock/doctype/warehouse/warehouse.json
+++ b/erpnext/stock/doctype/warehouse/warehouse.json
@@ -13,6 +13,7 @@
   "column_break_3",
   "warehouse_type",
   "parent_warehouse",
+  "default_in_transit_warehouse",
   "is_group",
   "column_break_4",
   "account",
@@ -230,13 +231,20 @@
   {
    "fieldname": "column_break_3",
    "fieldtype": "Section Break"
+  },
+  {
+   "depends_on": "eval: doc.warehouse_type !== 'Transit';",
+   "fieldname": "default_in_transit_warehouse",
+   "fieldtype": "Link",
+   "label": "Default In-Transit Warehouse",
+   "options": "Warehouse"
   }
  ],
  "icon": "fa fa-building",
  "idx": 1,
  "is_tree": 1,
  "links": [],
- "modified": "2020-08-03 18:41:52.442502",
+ "modified": "2021-02-16 17:21:52.380098",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Warehouse",
diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py
index 873cfec..01b6e71 100644
--- a/erpnext/stock/get_item_details.py
+++ b/erpnext/stock/get_item_details.py
@@ -917,11 +917,26 @@
 		{"item_code": item_code, "warehouse": warehouse}, "projected_qty")}
 
 @frappe.whitelist()
-def get_bin_details(item_code, warehouse):
-	return frappe.db.get_value("Bin", {"item_code": item_code, "warehouse": warehouse},
+def get_bin_details(item_code, warehouse, company=None):
+	bin_details = frappe.db.get_value("Bin", {"item_code": item_code, "warehouse": warehouse},
 		["projected_qty", "actual_qty", "reserved_qty"], as_dict=True, cache=True) \
 			or {"projected_qty": 0, "actual_qty": 0, "reserved_qty": 0}
+	if company:
+		bin_details['company_total_stock'] = get_company_total_stock(item_code, company)
+	return bin_details
 
+def get_company_total_stock(item_code, company):
+	return frappe.db.sql("""SELECT sum(actual_qty) from 
+		(`tabBin` INNER JOIN `tabWarehouse` ON `tabBin`.warehouse = `tabWarehouse`.name) 
+		WHERE `tabWarehouse`.company = '{0}' and `tabBin`.item_code = '{1}'"""
+		.format(company, item_code))[0][0]
+
+@frappe.whitelist()
+def get_total_stock_value(item_code):
+	query = """select sum(actual_qty) from `tabBin`, `tabItem` where
+		 `tabItem`.name = `tabBin`.item_code and ifnull(`tabItem`.disabled, 0) = 0  and `tabBin`.item_code = %(item_code)s"""
+	return frappe.db.sql(query, debug=True)
+	
 @frappe.whitelist()
 def get_serial_no_details(item_code, warehouse, stock_qty, serial_no):
 	args = frappe._dict({"item_code":item_code, "warehouse":warehouse, "stock_qty":stock_qty, "serial_no":serial_no})
diff --git a/erpnext/stock/report/stock_ledger/stock_ledger.js b/erpnext/stock/report/stock_ledger/stock_ledger.js
index 6f12c27..fe2417b 100644
--- a/erpnext/stock/report/stock_ledger/stock_ledger.js
+++ b/erpnext/stock/report/stock_ledger/stock_ledger.js
@@ -82,11 +82,6 @@
 			"label": __("Include UOM"),
 			"fieldtype": "Link",
 			"options": "UOM"
-		},
-		{
-			"fieldname": "show_cancelled_entries",
-			"label": __("Show Cancelled Entries"),
-			"fieldtype": "Check"
 		}
 	],
 	"formatter": function (value, row, column, data, default_formatter) {
diff --git a/erpnext/stock/report/stock_ledger/stock_ledger.py b/erpnext/stock/report/stock_ledger/stock_ledger.py
index 7b5701a..36996e9 100644
--- a/erpnext/stock/report/stock_ledger/stock_ledger.py
+++ b/erpnext/stock/report/stock_ledger/stock_ledger.py
@@ -138,7 +138,7 @@
 			`tabStock Ledger Entry` sle
 		WHERE
 			company = %(company)s
-				AND posting_date BETWEEN %(from_date)s AND %(to_date)s
+				AND is_cancelled = 0 AND posting_date BETWEEN %(from_date)s AND %(to_date)s
 				{sle_conditions}
 				{item_conditions_sql}
 		ORDER BY
@@ -209,9 +209,6 @@
 	if filters.get("project"):
 		conditions.append("project=%(project)s")
 
-	if not filters.get("show_cancelled_entries"):
-		conditions.append("is_cancelled = 0")
-
 	return "and {}".format(" and ".join(conditions)) if conditions else ""
 
 
diff --git a/erpnext/www/lms/index.py b/erpnext/www/lms/index.py
index 00f66e7..26f59a2 100644
--- a/erpnext/www/lms/index.py
+++ b/erpnext/www/lms/index.py
@@ -13,4 +13,4 @@
 
 
 def get_featured_programs():
-	return utils.get_portal_programs()
\ No newline at end of file
+	return utils.get_portal_programs() or []
\ No newline at end of file
diff --git a/erpnext/www/lms/program.py b/erpnext/www/lms/program.py
index d3b04c2..104d3fa 100644
--- a/erpnext/www/lms/program.py
+++ b/erpnext/www/lms/program.py
@@ -26,4 +26,4 @@
 
 def get_course_progress(courses, program):
 	progress = {course.name: utils.get_course_progress(course, program) for course in courses}
-	return progress
\ No newline at end of file
+	return progress or {}
\ No newline at end of file