fix: merge conflict
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/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py
index 97a89b6..8acd92c 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.py
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py
@@ -244,7 +244,7 @@
 		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":
@@ -612,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):
@@ -950,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
@@ -973,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:
@@ -1178,7 +1182,7 @@
 		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 == "Fees":
 		party_type = "Student"
@@ -1197,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
@@ -1245,6 +1251,9 @@
 	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)
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/patches.txt b/erpnext/patches.txt
index f27d228..59b12f3 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -757,4 +757,5 @@
 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
\ No newline at end of file
+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/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/payroll/doctype/gratuity/__init__.py b/erpnext/payroll/doctype/gratuity/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/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/payroll/doctype/gratuity_applicable_component/__init__.py b/erpnext/payroll/doctype/gratuity_applicable_component/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/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/payroll/doctype/gratuity_rule/__init__.py b/erpnext/payroll/doctype/gratuity_rule/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/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/payroll/doctype/gratuity_rule/test_gratuity_rule.py b/erpnext/payroll/doctype/gratuity_rule/test_gratuity_rule.py
new file mode 100644
index 0000000..1f5dc4e
--- /dev/null
+++ b/erpnext/payroll/doctype/gratuity_rule/test_gratuity_rule.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
+# See license.txt
+from __future__ import unicode_literals
+
+# import frappe
+import unittest
+
+class TestGratuityRule(unittest.TestCase):
+	pass
diff --git a/erpnext/payroll/doctype/gratuity_rule_slab/__init__.py b/erpnext/payroll/doctype/gratuity_rule_slab/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/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 02b9dd2..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):
@@ -574,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, {
diff --git a/erpnext/payroll/doctype/salary_slip/test_salary_slip.py b/erpnext/payroll/doctype/salary_slip/test_salary_slip.py
index f58a8e5..7289933 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")
diff --git a/erpnext/regional/india/setup.py b/erpnext/regional/india/setup.py
index fa197e3..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():
@@ -839,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/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
+	}]