Merge pull request #21605 from deepeshgarg007/loan_security_unpledge_fixes

fix: Loan security unpledge fixes
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py
index bcb22f0..83c670e 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.py
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py
@@ -228,6 +228,8 @@
 			valid_reference_doctypes = ("Purchase Order", "Purchase Invoice", "Journal Entry")
 		elif self.party_type == "Employee":
 			valid_reference_doctypes = ("Expense Claim", "Journal Entry", "Employee Advance")
+		elif self.party_type == "Shareholder":
+			valid_reference_doctypes = ("Journal Entry")
 
 		for d in self.get("references"):
 			if not d.allocated_amount:
diff --git a/erpnext/accounts/party.py b/erpnext/accounts/party.py
index 6e5b33f..528fb4e 100644
--- a/erpnext/accounts/party.py
+++ b/erpnext/accounts/party.py
@@ -162,7 +162,7 @@
 def set_price_list(party_details, party, party_type, given_price_list, pos=None):
 	# price list
 	price_list = get_permitted_documents('Price List')
-	
+
 	# if there is only one permitted document based on user permissions, set it
 	if price_list and len(price_list) == 1:
 		price_list = price_list[0]
@@ -465,23 +465,25 @@
 	from frappe.desk.form.load import get_communication_data
 
 	out = {}
-	fields = 'date(creation), count(name)'
+	fields = 'creation, count(*)'
 	after = add_years(None, -1).strftime('%Y-%m-%d')
-	group_by='group by date(creation)'
+	group_by='group by Date(creation)'
 
-	data = get_communication_data(doctype, name, after=after, group_by='group by date(creation)',
-		fields='date(C.creation) as creation, count(C.name)',as_dict=False)
+	data = get_communication_data(doctype, name, after=after, group_by='group by creation',
+		fields='C.creation as creation, count(C.name)',as_dict=False)
 
 	# fetch and append data from Activity Log
 	data += frappe.db.sql("""select {fields}
 		from `tabActivity Log`
-		where (reference_doctype="{doctype}" and reference_name="{name}")
-		or (timeline_doctype in ("{doctype}") and timeline_name="{name}")
-		or (reference_doctype in ("Quotation", "Opportunity") and timeline_name="{name}")
+		where (reference_doctype=%(doctype)s and reference_name=%(name)s)
+		or (timeline_doctype in (%(doctype)s) and timeline_name=%(name)s)
+		or (reference_doctype in ("Quotation", "Opportunity") and timeline_name=%(name)s)
 		and status!='Success' and creation > {after}
 		{group_by} order by creation desc
-		""".format(doctype=frappe.db.escape(doctype), name=frappe.db.escape(name), fields=fields,
-			group_by=group_by, after=after), as_dict=False)
+		""".format(fields=fields, group_by=group_by, after=after), {
+			"doctype": doctype,
+			"name": name
+		}, as_dict=False)
 
 	timeline_items = dict(data)
 
diff --git a/erpnext/accounts/report/general_ledger/general_ledger.py b/erpnext/accounts/report/general_ledger/general_ledger.py
index 7af5fa8..6afe208 100644
--- a/erpnext/accounts/report/general_ledger/general_ledger.py
+++ b/erpnext/accounts/report/general_ledger/general_ledger.py
@@ -296,6 +296,9 @@
 		data[key].debit_in_account_currency += flt(gle.debit_in_account_currency)
 		data[key].credit_in_account_currency += flt(gle.credit_in_account_currency)
 
+		if data[key].against_voucher:
+			data[key].against_voucher += ', ' + gle.against_voucher
+
 	from_date, to_date = getdate(filters.from_date), getdate(filters.to_date)
 	for gle in gl_entries:
 		if (gle.posting_date < from_date or
diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py
index 06dfa19..a3200d5 100644
--- a/erpnext/assets/doctype/asset/asset.py
+++ b/erpnext/assets/doctype/asset/asset.py
@@ -32,7 +32,7 @@
 		self.validate_in_use_date()
 		self.set_status()
 		self.make_asset_movement()
-		if not self.booked_fixed_asset and is_cwip_accounting_enabled(self.asset_category):
+		if not self.booked_fixed_asset and self.validate_make_gl_entry():
 			self.make_gl_entries()
 
 	def before_cancel(self):
@@ -455,18 +455,55 @@
 			for d in self.get('finance_books'):
 				if d.finance_book == self.default_finance_book:
 					return cint(d.idx) - 1
+	
+	def validate_make_gl_entry(self):
+		purchase_document = self.get_purchase_document()
+		asset_bought_with_invoice = purchase_document == self.purchase_invoice
+		fixed_asset_account, cwip_account = self.get_asset_accounts()
+		cwip_enabled = is_cwip_accounting_enabled(self.asset_category)
+		# check if expense already has been booked in case of cwip was enabled after purchasing asset
+		expense_booked = False
+		cwip_booked = False
+
+		if asset_bought_with_invoice:
+			expense_booked = frappe.db.sql("""SELECT name FROM `tabGL Entry` WHERE voucher_no = %s and account = %s""",
+				(purchase_document, fixed_asset_account), as_dict=1)
+		else:
+			cwip_booked = frappe.db.sql("""SELECT name FROM `tabGL Entry` WHERE voucher_no = %s and account = %s""",
+				(purchase_document, cwip_account), as_dict=1)
+
+		if cwip_enabled and (expense_booked or not cwip_booked):
+			# if expense has already booked from invoice or cwip is booked from receipt
+			return False
+		elif not cwip_enabled and (not expense_booked or cwip_booked):
+			# if cwip is disabled but expense hasn't been booked yet
+			return True
+		elif cwip_enabled:
+			# default condition
+			return True
+
+	def get_purchase_document(self):
+		asset_bought_with_invoice = self.purchase_invoice and frappe.db.get_value('Purchase Invoice', self.purchase_invoice, 'update_stock')
+		purchase_document = self.purchase_invoice if asset_bought_with_invoice else self.purchase_receipt
+
+		return purchase_document
+	
+	def get_asset_accounts(self):
+		fixed_asset_account = get_asset_category_account('fixed_asset_account', asset=self.name,
+					asset_category = self.asset_category, company = self.company)
+
+		cwip_account = get_asset_account("capital_work_in_progress_account",
+			self.name, self.asset_category, self.company)
+		
+		return fixed_asset_account, cwip_account
 
 	def make_gl_entries(self):
 		gl_entries = []
 
-		if ((self.purchase_receipt \
-			or (self.purchase_invoice and frappe.db.get_value('Purchase Invoice', self.purchase_invoice, 'update_stock')))
-			and self.purchase_receipt_amount and self.available_for_use_date <= nowdate()):
-			fixed_asset_account = get_asset_category_account('fixed_asset_account', asset=self.name,
-					asset_category = self.asset_category, company = self.company)
+		purchase_document = self.get_purchase_document()
+		fixed_asset_account, cwip_account = self.get_asset_accounts()
 
-			cwip_account = get_asset_account("capital_work_in_progress_account",
-				self.name, self.asset_category, self.company)
+		if (purchase_document and self.purchase_receipt_amount and self.available_for_use_date <= nowdate()):
 
 			gl_entries.append(self.get_gl_dict({
 				"account": cwip_account,
diff --git a/erpnext/assets/doctype/asset/test_asset.py b/erpnext/assets/doctype/asset/test_asset.py
index a0f8d15..aed78e7 100644
--- a/erpnext/assets/doctype/asset/test_asset.py
+++ b/erpnext/assets/doctype/asset/test_asset.py
@@ -560,6 +560,81 @@
 
 		self.assertEqual(gle, expected_gle)
 
+	def test_gle_with_cwip_toggling(self):
+		# TEST: purchase an asset with cwip enabled and then disable cwip and try submitting the asset
+		frappe.db.set_value("Asset Category", "Computers", "enable_cwip_accounting", 1)
+
+		pr = make_purchase_receipt(item_code="Macbook Pro",
+			qty=1, rate=5000, do_not_submit=True, location="Test Location")
+		pr.set('taxes', [{
+			'category': 'Total',
+			'add_deduct_tax': 'Add',
+			'charge_type': 'On Net Total',
+			'account_head': '_Test Account Service Tax - _TC',
+			'description': '_Test Account Service Tax',
+			'cost_center': 'Main - _TC',
+			'rate': 5.0
+		}, {
+			'category': 'Valuation and Total',
+			'add_deduct_tax': 'Add',
+			'charge_type': 'On Net Total',
+			'account_head': '_Test Account Shipping Charges - _TC',
+			'description': '_Test Account Shipping Charges',
+			'cost_center': 'Main - _TC',
+			'rate': 5.0
+		}])
+		pr.submit()
+		expected_gle = (
+			("Asset Received But Not Billed - _TC", 0.0, 5250.0),
+			("CWIP Account - _TC", 5250.0, 0.0)
+		)
+		pr_gle = frappe.db.sql("""select account, debit, credit from `tabGL Entry`
+			where voucher_type='Purchase Receipt' and voucher_no = %s
+			order by account""", pr.name)
+		self.assertEqual(pr_gle, expected_gle)
+
+		pi = make_invoice(pr.name)
+		pi.submit()
+		expected_gle = (
+			("_Test Account Service Tax - _TC", 250.0, 0.0),
+			("_Test Account Shipping Charges - _TC", 250.0, 0.0),
+			("Asset Received But Not Billed - _TC", 5250.0, 0.0),
+			("Creditors - _TC", 0.0, 5500.0),
+			("Expenses Included In Asset Valuation - _TC", 0.0, 250.0),
+		)
+		pi_gle = frappe.db.sql("""select account, debit, credit from `tabGL Entry`
+			where voucher_type='Purchase Invoice' and voucher_no = %s
+			order by account""", pi.name)
+		self.assertEqual(pi_gle, expected_gle)
+
+		asset = frappe.db.get_value('Asset', {'purchase_receipt': pr.name, 'docstatus': 0}, 'name')
+		asset_doc = frappe.get_doc('Asset', asset)
+		month_end_date = get_last_day(nowdate())
+		asset_doc.available_for_use_date = nowdate() if nowdate() != month_end_date else add_days(nowdate(), -15)
+		self.assertEqual(asset_doc.gross_purchase_amount, 5250.0)
+		asset_doc.append("finance_books", {
+			"expected_value_after_useful_life": 200,
+			"depreciation_method": "Straight Line",
+			"total_number_of_depreciations": 3,
+			"frequency_of_depreciation": 10,
+			"depreciation_start_date": month_end_date
+		})
+
+		# disable cwip and try submitting
+		frappe.db.set_value("Asset Category", "Computers", "enable_cwip_accounting", 0)
+		asset_doc.submit()
+		# asset should have gl entries even if cwip is disabled
+		expected_gle = (
+			("_Test Fixed Asset - _TC", 5250.0, 0.0),
+			("CWIP Account - _TC", 0.0, 5250.0)
+		)
+		gle = frappe.db.sql("""select account, debit, credit from `tabGL Entry`
+			where voucher_type='Asset' and voucher_no = %s
+			order by account""", asset_doc.name)
+		self.assertEqual(gle, expected_gle)
+
+		frappe.db.set_value("Asset Category", "Computers", "enable_cwip_accounting", 1)
+
 	def test_expense_head(self):
 		pr = make_purchase_receipt(item_code="Macbook Pro",
 			qty=2, rate=200000.0, location="Test Location")
diff --git a/erpnext/assets/doctype/asset_movement/asset_movement.py b/erpnext/assets/doctype/asset_movement/asset_movement.py
index 3a08baa..3da355e 100644
--- a/erpnext/assets/doctype/asset_movement/asset_movement.py
+++ b/erpnext/assets/doctype/asset_movement/asset_movement.py
@@ -110,6 +110,7 @@
 				ORDER BY
 					asm.transaction_date asc
 				""", (d.asset, self.company, 'Receipt'), as_dict=1)
+
 			if auto_gen_movement_entry and auto_gen_movement_entry[0].get('name') == self.name:
 				frappe.throw(_('{0} will be cancelled automatically on asset cancellation as it was \
 					auto generated for Asset {1}').format(self.name, d.asset))
diff --git a/erpnext/controllers/sales_and_purchase_return.py b/erpnext/controllers/sales_and_purchase_return.py
index 81fdbbe..90c67f1 100644
--- a/erpnext/controllers/sales_and_purchase_return.py
+++ b/erpnext/controllers/sales_and_purchase_return.py
@@ -74,7 +74,7 @@
 	for d in doc.get("items"):
 		if d.item_code and (flt(d.qty) < 0 or flt(d.get('received_qty')) < 0):
 			if d.item_code not in valid_items:
-				frappe.throw(_("Row # {0}: Returned Item {1} does not exists in {2} {3}")
+				frappe.throw(_("Row # {0}: Returned Item {1} does not exist in {2} {3}")
 					.format(d.idx, d.item_code, doc.doctype, doc.return_against))
 			else:
 				ref = valid_items.get(d.item_code, frappe._dict())
@@ -266,6 +266,8 @@
 			target_doc.purchase_order = source_doc.purchase_order
 			target_doc.purchase_order_item = source_doc.purchase_order_item
 			target_doc.rejected_warehouse = source_doc.rejected_warehouse
+			target_doc.purchase_receipt_item = source_doc.name
+
 		elif doctype == "Purchase Invoice":
 			target_doc.received_qty = -1* source_doc.received_qty
 			target_doc.rejected_qty = -1* source_doc.rejected_qty
@@ -282,6 +284,7 @@
 			target_doc.so_detail = source_doc.so_detail
 			target_doc.si_detail = source_doc.si_detail
 			target_doc.expense_account = source_doc.expense_account
+			target_doc.dn_detail = source_doc.name
 			if default_warehouse_for_sales_return:
 				target_doc.warehouse = default_warehouse_for_sales_return
 		elif doctype == "Sales Invoice":
diff --git a/erpnext/controllers/selling_controller.py b/erpnext/controllers/selling_controller.py
index 90ba8b3..1e0a48c 100644
--- a/erpnext/controllers/selling_controller.py
+++ b/erpnext/controllers/selling_controller.py
@@ -165,9 +165,9 @@
 				d.stock_qty = flt(d.qty) * flt(d.conversion_factor)
 
 	def validate_selling_price(self):
-		def throw_message(item_name, rate, ref_rate_field):
-			frappe.throw(_("""Selling rate for item {0} is lower than its {1}. Selling rate should be atleast {2}""")
-				.format(item_name, ref_rate_field, rate))
+		def throw_message(idx, item_name, rate, ref_rate_field):
+			frappe.throw(_("""Row #{}: Selling rate for item {} is lower than its {}. Selling rate should be atleast {}""")
+				.format(idx, item_name, ref_rate_field, rate))
 
 		if not frappe.db.get_single_value("Selling Settings", "validate_selling_price"):
 			return
@@ -181,8 +181,8 @@
 
 			last_purchase_rate, is_stock_item = frappe.get_cached_value("Item", it.item_code, ["last_purchase_rate", "is_stock_item"])
 			last_purchase_rate_in_sales_uom = last_purchase_rate / (it.conversion_factor or 1)
-			if flt(it.base_rate) < flt(last_purchase_rate_in_sales_uom) and not self.get('is_internal_customer'):
-				throw_message(it.item_name, last_purchase_rate_in_sales_uom, "last purchase rate")
+			if flt(it.base_rate) < flt(last_purchase_rate_in_sales_uom):
+				throw_message(it.idx, frappe.bold(it.item_name), last_purchase_rate_in_sales_uom, "last purchase rate")
 
 			last_valuation_rate = frappe.db.sql("""
 				SELECT valuation_rate FROM `tabStock Ledger Entry` WHERE item_code = %s
@@ -193,7 +193,7 @@
 				last_valuation_rate_in_sales_uom = last_valuation_rate[0][0] / (it.conversion_factor or 1)
 				if is_stock_item and flt(it.base_rate) < flt(last_valuation_rate_in_sales_uom) \
 					and not self.get('is_internal_customer'):
-					throw_message(it.name, last_valuation_rate_in_sales_uom, "valuation rate")
+					throw_message(it.idx, frappe.bold(it.item_name), last_valuation_rate_in_sales_uom, "valuation rate")
 
 
 	def get_item_list(self):
diff --git a/erpnext/healthcare/desk_page/healthcare/healthcare.json b/erpnext/healthcare/desk_page/healthcare/healthcare.json
index 24c6d6f..5cf09b3 100644
--- a/erpnext/healthcare/desk_page/healthcare/healthcare.json
+++ b/erpnext/healthcare/desk_page/healthcare/healthcare.json
@@ -47,7 +47,12 @@
   }
  ],
  "category": "Domains",
- "charts": [],
+ "charts": [
+  {
+   "chart_name": "Patient Appointments",
+   "label": "Patient Appointments"
+  }
+ ],
  "charts_label": "",
  "creation": "2020-03-02 17:23:17.919682",
  "developer_mode_only": 0,
@@ -58,7 +63,7 @@
  "idx": 0,
  "is_standard": 1,
  "label": "Healthcare",
- "modified": "2020-04-20 11:42:43.889576",
+ "modified": "2020-04-25 22:31:36.576444",
  "modified_by": "Administrator",
  "module": "Healthcare",
  "name": "Healthcare",
diff --git a/erpnext/hr/doctype/additional_salary/additional_salary.js b/erpnext/hr/doctype/additional_salary/additional_salary.js
index 18f6b8b..fb42b6f 100644
--- a/erpnext/hr/doctype/additional_salary/additional_salary.js
+++ b/erpnext/hr/doctype/additional_salary/additional_salary.js
@@ -13,5 +13,5 @@
 				}
 			};
 		});
-	}
+	},
 });
diff --git a/erpnext/hr/doctype/additional_salary/additional_salary.json b/erpnext/hr/doctype/additional_salary/additional_salary.json
index 7d69f7e..bfb543f 100644
--- a/erpnext/hr/doctype/additional_salary/additional_salary.json
+++ b/erpnext/hr/doctype/additional_salary/additional_salary.json
@@ -13,10 +13,14 @@
   "salary_component",
   "overwrite_salary_structure_amount",
   "deduct_full_tax_on_selected_payroll_date",
+  "ref_doctype",
+  "ref_docname",
   "column_break_5",
   "company",
+  "is_recurring",
+  "from_date",
+  "to_date",
   "payroll_date",
-  "salary_slip",
   "type",
   "department",
   "amount",
@@ -74,12 +78,13 @@
    "fieldtype": "Column Break"
   },
   {
+   "depends_on": "eval:(doc.is_recurring==0)",
    "description": "Date on which this component is applied",
    "fieldname": "payroll_date",
    "fieldtype": "Date",
    "in_list_view": 1,
    "label": "Payroll Date",
-   "reqd": 1,
+   "mandatory_depends_on": "eval:(doc.is_recurring==0)",
    "search_index": 1
   },
   {
@@ -106,13 +111,6 @@
    "reqd": 1
   },
   {
-   "fieldname": "salary_slip",
-   "fieldtype": "Link",
-   "label": "Salary Slip",
-   "options": "Salary Slip",
-   "read_only": 1
-  },
-  {
    "fetch_from": "salary_component.type",
    "fieldname": "type",
    "fieldtype": "Data",
@@ -127,11 +125,45 @@
    "options": "Additional Salary",
    "print_hide": 1,
    "read_only": 1
+  },
+  {
+   "default": "0",
+   "fieldname": "is_recurring",
+   "fieldtype": "Check",
+   "label": "Is Recurring"
+  },
+  {
+   "depends_on": "eval:(doc.is_recurring==1)",
+   "fieldname": "from_date",
+   "fieldtype": "Date",
+   "label": "From Date",
+   "mandatory_depends_on": "eval:(doc.is_recurring==1)"
+  },
+  {
+   "depends_on": "eval:(doc.is_recurring==1)",
+   "fieldname": "to_date",
+   "fieldtype": "Date",
+   "label": "To Date",
+   "mandatory_depends_on": "eval:(doc.is_recurring==1)"
+  },
+   {
+   "fieldname": "ref_doctype",
+   "fieldtype": "Link",
+   "label": "Reference Document Type",
+   "options": "DocType",
+   "read_only": 1
+  },
+  {
+   "fieldname": "ref_docname",
+   "fieldtype": "Dynamic Link",
+   "label": "Reference Document",
+   "options": "ref_doctype",
+   "read_only": 1
   }
  ],
  "is_submittable": 1,
  "links": [],
- "modified": "2019-12-12 19:07:23.635901",
+ "modified": "2020-04-04 18:06:29.170878",
  "modified_by": "Administrator",
  "module": "HR",
  "name": "Additional Salary",
diff --git a/erpnext/hr/doctype/additional_salary/additional_salary.py b/erpnext/hr/doctype/additional_salary/additional_salary.py
index bc7dcee..bab6fb5 100644
--- a/erpnext/hr/doctype/additional_salary/additional_salary.py
+++ b/erpnext/hr/doctype/additional_salary/additional_salary.py
@@ -9,6 +9,11 @@
 from frappe.utils import getdate, date_diff
 
 class AdditionalSalary(Document):
+
+	def on_submit(self):
+		if self.ref_doctype == "Employee Advance" and self.ref_docname:
+			frappe.db.set_value("Employee Advance", self.ref_docname, "return_amount", self.amount)
+
 	def before_insert(self):
 		if frappe.db.exists("Additional Salary", {"employee": self.employee, "salary_component": self.salary_component,
 			"amount": self.amount, "payroll_date": self.payroll_date, "company": self.company, "docstatus": 1}):
@@ -21,10 +26,19 @@
 			frappe.throw(_("Amount should not be less than zero."))
 
 	def validate_dates(self):
- 		date_of_joining, relieving_date = frappe.db.get_value("Employee", self.employee,
+		date_of_joining, relieving_date = frappe.db.get_value("Employee", self.employee,
 			["date_of_joining", "relieving_date"])
- 		if date_of_joining and getdate(self.payroll_date) < getdate(date_of_joining):
- 			frappe.throw(_("Payroll date can not be less than employee's joining date"))
+
+		if getdate(self.from_date) > getdate(self.to_date):
+			frappe.throw(_("From Date can not be greater than To Date."))
+
+		if date_of_joining:
+			if getdate(self.payroll_date) < getdate(date_of_joining):
+				frappe.throw(_("Payroll date can not be less than employee's joining date."))
+			elif getdate(self.from_date) < getdate(date_of_joining):
+				frappe.throw(_("From date can not be less than employee's joining date."))
+			elif getdate(self.to_date) > getdate(relieving_date):
+				frappe.throw(_("To date can not be greater than employee's relieving date."))
 
 	def get_amount(self, sal_start_date, sal_end_date):
 		start_date = getdate(sal_start_date)
@@ -40,15 +54,18 @@
 
 @frappe.whitelist()
 def get_additional_salary_component(employee, start_date, end_date, component_type):
-	additional_components = frappe.db.sql("""
-		select salary_component, sum(amount) as amount, overwrite_salary_structure_amount, deduct_full_tax_on_selected_payroll_date
+	additional_salaries = frappe.db.sql("""
+		select name, salary_component, type, amount, overwrite_salary_structure_amount, deduct_full_tax_on_selected_payroll_date
 		from `tabAdditional Salary`
 		where employee=%(employee)s
 			and docstatus = 1
-			and payroll_date between %(from_date)s and %(to_date)s
-			and type = %(component_type)s
-		group by salary_component, overwrite_salary_structure_amount
-		order by salary_component, overwrite_salary_structure_amount
+			and (
+					payroll_date between %(from_date)s and %(to_date)s
+				or
+					from_date <= %(to_date)s and to_date >= %(to_date)s
+				)
+		and type = %(component_type)s
+		order by salary_component, overwrite_salary_structure_amount DESC
 	""", {
 		'employee': employee,
 		'from_date': start_date,
@@ -56,21 +73,38 @@
 		'component_type': "Earning" if component_type == "earnings" else "Deduction"
 	}, as_dict=1)
 
-	additional_components_list = []
+	existing_salary_components= []
+	salary_components_details = {}
+	additional_salary_details = []
+
+	overwrites_components = [ele.salary_component for ele in additional_salaries if ele.overwrite_salary_structure_amount == 1]
+
 	component_fields = ["depends_on_payment_days", "salary_component_abbr", "is_tax_applicable", "variable_based_on_taxable_salary", 'type']
-	for d in additional_components:
-		struct_row = frappe._dict({'salary_component': d.salary_component})
-		component = frappe.get_all("Salary Component", filters={'name': d.salary_component}, fields=component_fields)
-		if component:
-			struct_row.update(component[0])
+	for d in additional_salaries:
 
-		struct_row['deduct_full_tax_on_selected_payroll_date'] = d.deduct_full_tax_on_selected_payroll_date
-		struct_row['is_additional_component'] = 1
+		if d.salary_component not in existing_salary_components:
+			component = frappe.get_all("Salary Component", filters={'name': d.salary_component}, fields=component_fields)
+			struct_row = frappe._dict({'salary_component': d.salary_component})
+			if component:
+				struct_row.update(component[0])
 
-		additional_components_list.append(frappe._dict({
-			'amount': d.amount,
-			'type': component[0].type,
-			'struct_row': struct_row,
-			'overwrite': d.overwrite_salary_structure_amount,
-		}))
-	return additional_components_list
\ No newline at end of file
+			struct_row['deduct_full_tax_on_selected_payroll_date'] = d.deduct_full_tax_on_selected_payroll_date
+			struct_row['is_additional_component'] = 1
+
+			salary_components_details[d.salary_component] = struct_row
+
+
+		if overwrites_components.count(d.salary_component) > 1:
+			frappe.throw(_("Multiple Additional Salaries with overwrite property exist for Salary Component: {0} between {1} and {2}.".format(d.salary_component, start_date, end_date)), title=_("Error"))
+		else:
+			additional_salary_details.append({
+				'name': d.name,
+				'component': d.salary_component,
+				'amount': d.amount,
+				'type': d.type,
+				'overwrite': d.overwrite_salary_structure_amount,
+			})
+
+		existing_salary_components.append(d.salary_component)
+
+	return salary_components_details, additional_salary_details
\ No newline at end of file
diff --git a/erpnext/hr/doctype/additional_salary/test_additional_salary.py b/erpnext/hr/doctype/additional_salary/test_additional_salary.py
index 949ba20..6f93fb5 100644
--- a/erpnext/hr/doctype/additional_salary/test_additional_salary.py
+++ b/erpnext/hr/doctype/additional_salary/test_additional_salary.py
@@ -3,6 +3,44 @@
 # See license.txt
 from __future__ import unicode_literals
 import unittest
+import frappe, erpnext
+from frappe.utils import nowdate, add_days
+from erpnext.hr.doctype.employee.test_employee import make_employee
+from erpnext.hr.doctype.salary_component.test_salary_component import create_salary_component
+from erpnext.hr.doctype.salary_slip.test_salary_slip import make_employee_salary_slip, setup_test
+
 
 class TestAdditionalSalary(unittest.TestCase):
-	pass
+
+	def setUp(self):
+		setup_test()
+
+	def test_recurring_additional_salary(self):
+		emp_id = make_employee("test_additional@salary.com")
+		frappe.db.set_value("Employee", emp_id, "relieving_date", add_days(nowdate(), 1800))
+		add_sal = get_additional_salary(emp_id)
+
+		ss = make_employee_salary_slip("test_additional@salary.com", "Monthly")
+		for earning in ss.earnings:
+			if earning.salary_component == "Recurring Salary Component":
+				amount = earning.amount
+				salary_component = earning.salary_component
+
+		self.assertEqual(amount, add_sal.amount)
+		self.assertEqual(salary_component, add_sal.salary_component)
+
+
+
+def get_additional_salary(emp_id):
+	create_salary_component("Recurring Salary Component")
+	add_sal = frappe.new_doc("Additional Salary")
+	add_sal.employee = emp_id
+	add_sal.salary_component = "Recurring Salary Component"
+	add_sal.is_recurring = 1
+	add_sal.from_date = add_days(nowdate(), -50)
+	add_sal.to_date = add_days(nowdate(), 180)
+	add_sal.amount = 5000
+	add_sal.save()
+	add_sal.submit()
+
+	return add_sal
diff --git a/erpnext/hr/doctype/employee_advance/employee_advance.js b/erpnext/hr/doctype/employee_advance/employee_advance.js
index 3896603..6cc49cf 100644
--- a/erpnext/hr/doctype/employee_advance/employee_advance.js
+++ b/erpnext/hr/doctype/employee_advance/employee_advance.js
@@ -23,6 +23,14 @@
 				}
 			};
 		});
+
+		frm.set_query('salary_component', function(doc) {
+			return {
+				filters: {
+					"type": "Deduction"
+				}
+			};
+		});
 	},
 
 	refresh: function(frm) {
@@ -47,19 +55,37 @@
 		}
 
 		if (frm.doc.docstatus === 1
-			&& (flt(frm.doc.claimed_amount) + flt(frm.doc.return_amount) < flt(frm.doc.paid_amount))
-			&& frappe.model.can_create("Journal Entry")) {
+			&& (flt(frm.doc.claimed_amount) < flt(frm.doc.paid_amount) && flt(frm.doc.paid_amount) != flt(frm.doc.return_amount))) {
 
-			frm.add_custom_button(__("Return"),  function() {
-				frm.trigger('make_return_entry');
-			}, __('Create'));
+			if (frm.doc.repay_unclaimed_amount_from_salary == 0 && frappe.model.can_create("Journal Entry")){
+				frm.add_custom_button(__("Return"),  function() {
+					frm.trigger('make_return_entry');
+				}, __('Create'));
+			}else if (frm.doc.repay_unclaimed_amount_from_salary == 1 && frappe.model.can_create("Additional Salary")){
+				frm.add_custom_button(__("Deduction from salary"),  function() {
+					frm.events.make_deduction_via_additional_salary(frm)
+				}, __('Create'));
+			}
 		}
 	},
 
+	make_deduction_via_additional_salary: function(frm){
+		frappe.call({
+			method: "erpnext.hr.doctype.employee_advance.employee_advance.create_return_through_additional_salary",
+			args: {
+				doc: frm.doc
+			},
+			callback: function (r){
+				var doclist = frappe.model.sync(r.message);
+				frappe.set_route("Form", doclist[0].doctype, doclist[0].name);
+			}
+		});
+	},
+
 	make_payment_entry: function(frm) {
 		var method = "erpnext.accounts.doctype.payment_entry.payment_entry.get_payment_entry";
 		if(frm.doc.__onload && frm.doc.__onload.make_payment_via_journal_entry) {
-			method = "erpnext.hr.doctype.employee_advance.employee_advance.make_bank_entry"
+			method = "erpnext.hr.doctype.employee_advance.employee_advance.make_bank_entry";
 		}
 		return frappe.call({
 			method: method,
diff --git a/erpnext/hr/doctype/employee_advance/employee_advance.json b/erpnext/hr/doctype/employee_advance/employee_advance.json
index d233a2b..8c5ce42 100644
--- a/erpnext/hr/doctype/employee_advance/employee_advance.json
+++ b/erpnext/hr/doctype/employee_advance/employee_advance.json
@@ -10,9 +10,10 @@
   "naming_series",
   "employee",
   "employee_name",
+  "department",
   "column_break_4",
   "posting_date",
-  "department",
+  "repay_unclaimed_amount_from_salary",
   "section_break_8",
   "purpose",
   "column_break_11",
@@ -164,16 +165,23 @@
    "options": "Mode of Payment"
   },
   {
+   "allow_on_submit": 1,
    "fieldname": "return_amount",
    "fieldtype": "Currency",
    "label": "Returned Amount",
    "options": "Company:company:default_currency",
    "read_only": 1
+  },
+  {
+   "default": "0",
+   "fieldname": "repay_unclaimed_amount_from_salary",
+   "fieldtype": "Check",
+   "label": "Repay unclaimed amount from salary"
   }
  ],
  "is_submittable": 1,
  "links": [],
- "modified": "2019-12-15 19:04:07.044505",
+ "modified": "2020-03-06 15:11:33.747535",
  "modified_by": "Administrator",
  "module": "HR",
  "name": "Employee Advance",
@@ -210,4 +218,4 @@
  "sort_field": "modified",
  "sort_order": "DESC",
  "track_changes": 1
-}
+}
\ No newline at end of file
diff --git a/erpnext/hr/doctype/employee_advance/employee_advance.py b/erpnext/hr/doctype/employee_advance/employee_advance.py
index f0663ae..23e4992 100644
--- a/erpnext/hr/doctype/employee_advance/employee_advance.py
+++ b/erpnext/hr/doctype/employee_advance/employee_advance.py
@@ -133,8 +133,20 @@
 	return je.as_dict()
 
 @frappe.whitelist()
-def make_return_entry(employee, company, employee_advance_name,
-		return_amount, advance_account, mode_of_payment=None):
+def create_return_through_additional_salary(doc):
+	import json
+	doc = frappe._dict(json.loads(doc))
+	additional_salary = frappe.new_doc('Additional Salary')
+	additional_salary.employee = doc.employee
+	additional_salary.amount = doc.paid_amount - doc.claimed_amount
+	additional_salary.company = doc.company
+	additional_salary.ref_doctype = doc.doctype
+	additional_salary.ref_docname = doc.name
+
+	return additional_salary
+
+@frappe.whitelist()
+def make_return_entry(employee_name, company, employee_advance_name, return_amount, mode_of_payment, advance_account):
 	return_account = get_default_bank_cash_account(company, account_type='Cash', mode_of_payment = mode_of_payment)
 
 	mode_of_payment_type = ''
diff --git a/erpnext/hr/doctype/employee_incentive/employee_incentive.json b/erpnext/hr/doctype/employee_incentive/employee_incentive.json
index ce8e1ea..e2d8a11 100644
--- a/erpnext/hr/doctype/employee_incentive/employee_incentive.json
+++ b/erpnext/hr/doctype/employee_incentive/employee_incentive.json
@@ -9,10 +9,9 @@
   "employee",
   "incentive_amount",
   "employee_name",
-  "additional_salary",
+  "salary_component",
   "column_break_5",
   "payroll_date",
-  "salary_component",
   "department",
   "amended_from"
  ],
@@ -66,14 +65,6 @@
    "read_only": 1
   },
   {
-   "fieldname": "additional_salary",
-   "fieldtype": "Link",
-   "label": "Additional Salary",
-   "no_copy": 1,
-   "options": "Additional Salary",
-   "read_only": 1
-  },
-  {
    "fieldname": "salary_component",
    "fieldtype": "Link",
    "label": "Salary Component",
@@ -83,7 +74,7 @@
  ],
  "is_submittable": 1,
  "links": [],
- "modified": "2019-12-12 13:24:44.761540",
+ "modified": "2020-03-05 18:59:40.526014",
  "modified_by": "Administrator",
  "module": "HR",
  "name": "Employee Incentive",
diff --git a/erpnext/hr/doctype/employee_incentive/employee_incentive.py b/erpnext/hr/doctype/employee_incentive/employee_incentive.py
index 2e138f8..44763fc 100644
--- a/erpnext/hr/doctype/employee_incentive/employee_incentive.py
+++ b/erpnext/hr/doctype/employee_incentive/employee_incentive.py
@@ -9,37 +9,13 @@
 class EmployeeIncentive(Document):
 	def on_submit(self):
 		company = frappe.db.get_value('Employee', self.employee, 'company')
-		additional_salary = frappe.db.exists('Additional Salary', {
-				'employee': self.employee, 
-				'salary_component': self.salary_component,
-				'payroll_date': self.payroll_date, 
-				'company': company,
-				'docstatus': 1
-			})
 
-		if not additional_salary:
-			additional_salary = frappe.new_doc('Additional Salary')
-			additional_salary.employee = self.employee
-			additional_salary.salary_component = self.salary_component
-			additional_salary.amount = self.incentive_amount
-			additional_salary.payroll_date = self.payroll_date
-			additional_salary.company = company
-			additional_salary.submit()
-			self.db_set('additional_salary', additional_salary.name)
-
-		else:
-			incentive_added = frappe.db.get_value('Additional Salary', additional_salary, 'amount') + self.incentive_amount
-			frappe.db.set_value('Additional Salary', additional_salary, 'amount', incentive_added)
-			self.db_set('additional_salary', additional_salary)
-
-	def on_cancel(self):
-		if self.additional_salary:
-			incentive_removed = frappe.db.get_value('Additional Salary', self.additional_salary, 'amount') - self.incentive_amount
-			if incentive_removed == 0:
-				frappe.get_doc('Additional Salary', self.additional_salary).cancel()
-			else:
-				frappe.db.set_value('Additional Salary', self.additional_salary, 'amount', incentive_removed)
-
-			self.db_set('additional_salary', '')
-
-		
+		additional_salary = frappe.new_doc('Additional Salary')
+		additional_salary.employee = self.employee
+		additional_salary.salary_component = self.salary_component
+		additional_salary.amount = self.incentive_amount
+		additional_salary.payroll_date = self.payroll_date
+		additional_salary.company = company
+		additional_salary.ref_doctype = self.doctype
+		additional_salary.ref_docname = self.name
+		additional_salary.submit()
diff --git a/erpnext/hr/doctype/holiday/holiday.json b/erpnext/hr/doctype/holiday/holiday.json
index 6498530..6bd0ab0 100644
--- a/erpnext/hr/doctype/holiday/holiday.json
+++ b/erpnext/hr/doctype/holiday/holiday.json
@@ -1,87 +1,60 @@
 {
- "allow_copy": 0, 
- "allow_import": 0, 
- "allow_rename": 0, 
- "beta": 0, 
- "creation": "2013-02-22 01:27:46", 
- "custom": 0, 
- "docstatus": 0, 
- "doctype": "DocType", 
- "document_type": "Setup", 
- "editable_grid": 1, 
+ "actions": [],
+ "creation": "2013-02-22 01:27:46",
+ "doctype": "DocType",
+ "document_type": "Setup",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "holiday_date",
+  "column_break_2",
+  "weekly_off",
+  "section_break_4",
+  "description"
+ ],
  "fields": [
   {
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "fieldname": "holiday_date", 
-   "fieldtype": "Date", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_list_view": 1, 
-   "label": "Date", 
-   "length": 0, 
-   "no_copy": 0, 
-   "oldfieldname": "holiday_date", 
-   "oldfieldtype": "Date", 
-   "permlevel": 0, 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "report_hide": 0, 
-   "reqd": 1, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "holiday_date",
+   "fieldtype": "Date",
+   "in_list_view": 1,
+   "label": "Date",
+   "oldfieldname": "holiday_date",
+   "oldfieldtype": "Date",
+   "reqd": 1
+  },
   {
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "fieldname": "description", 
-   "fieldtype": "Text Editor", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_list_view": 1, 
-   "label": "Description", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "print_width": "300px", 
-   "read_only": 0, 
-   "report_hide": 0, 
-   "reqd": 1, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "unique": 0, 
+   "fieldname": "description",
+   "fieldtype": "Text Editor",
+   "in_list_view": 1,
+   "label": "Description",
+   "print_width": "300px",
+   "reqd": 1,
    "width": "300px"
+  },
+  {
+   "default": "0",
+   "fieldname": "weekly_off",
+   "fieldtype": "Check",
+   "label": "Weekly Off"
+  },
+  {
+   "fieldname": "column_break_2",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "section_break_4",
+   "fieldtype": "Section Break"
   }
- ], 
- "hide_heading": 0, 
- "hide_toolbar": 0, 
- "idx": 1, 
- "image_view": 0, 
- "in_create": 0, 
-
- "is_submittable": 0, 
- "issingle": 0, 
- "istable": 1, 
- "max_attachments": 0, 
- "modified": "2016-07-11 03:28:00.660849", 
- "modified_by": "Administrator", 
- "module": "HR", 
- "name": "Holiday", 
- "owner": "Administrator", 
- "permissions": [], 
- "quick_entry": 0, 
- "read_only": 0, 
- "read_only_onload": 0, 
- "sort_order": "ASC", 
- "track_seen": 0
+ ],
+ "idx": 1,
+ "istable": 1,
+ "links": [],
+ "modified": "2020-04-18 19:03:23.507845",
+ "modified_by": "Administrator",
+ "module": "HR",
+ "name": "Holiday",
+ "owner": "Administrator",
+ "permissions": [],
+ "sort_field": "modified",
+ "sort_order": "ASC"
 }
\ No newline at end of file
diff --git a/erpnext/hr/doctype/holiday_list/holiday_list.py b/erpnext/hr/doctype/holiday_list/holiday_list.py
index 8c7b6f7..76dc942 100644
--- a/erpnext/hr/doctype/holiday_list/holiday_list.py
+++ b/erpnext/hr/doctype/holiday_list/holiday_list.py
@@ -23,6 +23,7 @@
 			ch = self.append('holidays', {})
 			ch.description = self.weekly_off
 			ch.holiday_date = d
+			ch.weekly_off = 1
 			ch.idx = last_idx + i + 1
 
 	def validate_values(self):
diff --git a/erpnext/hr/doctype/leave_encashment/leave_encashment.py b/erpnext/hr/doctype/leave_encashment/leave_encashment.py
index 7d6fd42..50a08b1 100644
--- a/erpnext/hr/doctype/leave_encashment/leave_encashment.py
+++ b/erpnext/hr/doctype/leave_encashment/leave_encashment.py
@@ -30,13 +30,16 @@
 		additional_salary = frappe.new_doc("Additional Salary")
 		additional_salary.company = frappe.get_value("Employee", self.employee, "company")
 		additional_salary.employee = self.employee
-		additional_salary.salary_component = frappe.get_value("Leave Type", self.leave_type, "earning_component")
+		earning_component = frappe.get_value("Leave Type", self.leave_type, "earning_component")
+		if not earning_component:
+			frappe.throw(_("Please set Earning Component for Leave type: {0}.".format(self.leave_type)))
+		additional_salary.salary_component = earning_component
 		additional_salary.payroll_date = self.encashment_date
 		additional_salary.amount = self.encashment_amount
+		additional_salary.ref_doctype = self.doctype
+		additional_salary.ref_docname = self.name
 		additional_salary.submit()
 
-		self.db_set("additional_salary", additional_salary.name)
-
 		# Set encashed leaves in Allocation
 		frappe.db.set_value("Leave Allocation", self.leave_allocation, "total_leaves_encashed",
 				frappe.db.get_value('Leave Allocation', self.leave_allocation, 'total_leaves_encashed') + self.encashable_days)
@@ -118,4 +121,4 @@
 			leave_type=allocation.leave_type,
 			encashment_date=allocation.to_date
 		))
-		leave_encashment.insert(ignore_permissions=True)
+		leave_encashment.insert(ignore_permissions=True)
\ No newline at end of file
diff --git a/erpnext/hr/doctype/leave_encashment/test_leave_encashment.py b/erpnext/hr/doctype/leave_encashment/test_leave_encashment.py
index e5bd170..ac7755b 100644
--- a/erpnext/hr/doctype/leave_encashment/test_leave_encashment.py
+++ b/erpnext/hr/doctype/leave_encashment/test_leave_encashment.py
@@ -53,7 +53,10 @@
 		self.assertEqual(leave_encashment.encashment_amount, 250)
 
 		leave_encashment.submit()
-		self.assertTrue(frappe.db.get_value("Leave Encashment", leave_encashment.name, "additional_salary"))
+
+		# assert links
+		add_sal = frappe.get_all("Additional Salary", filters = {"ref_docname": leave_encashment.name})[0]
+		self.assertTrue(add_sal)
 
 	def test_creation_of_leave_ledger_entry_on_submit(self):
 		frappe.db.sql('''delete from `tabLeave Encashment`''')
@@ -75,5 +78,8 @@
 		self.assertEquals(leave_ledger_entry[0].leaves, leave_encashment.encashable_days *  -1)
 
 		# check if leave ledger entry is deleted on cancellation
+
+		frappe.db.sql("Delete from `tabAdditional Salary` WHERE ref_docname = %s", (leave_encashment.name) )
+
 		leave_encashment.cancel()
 		self.assertFalse(frappe.db.exists("Leave Ledger Entry", {'transaction_name':leave_encashment.name}))
diff --git a/erpnext/hr/doctype/salary_detail/salary_detail.json b/erpnext/hr/doctype/salary_detail/salary_detail.json
index 545f56a..fe5f83b 100644
--- a/erpnext/hr/doctype/salary_detail/salary_detail.json
+++ b/erpnext/hr/doctype/salary_detail/salary_detail.json
@@ -26,6 +26,7 @@
   "tax_on_flexible_benefit",
   "tax_on_additional_salary",
   "section_break_11",
+  "additional_salary",
   "condition_and_formula_help"
  ],
  "fields": [
@@ -193,6 +194,12 @@
    "options": "<h3>Condition and Formula Help</h3>\n\n<p>Notes:</p>\n\n<ol>\n<li>Use field <code>base</code> for using base salary of the Employee</li>\n<li>Use Salary Component abbreviations in conditions and formulas. <code>BS = Basic Salary</code></li>\n<li>Use field name for employee details in conditions and formulas. <code>Employment Type = employment_type</code><code>Branch = branch</code></li>\n<li>Use field name from Salary Slip in conditions and formulas. <code>Payment Days = payment_days</code><code>Leave without pay = leave_without_pay</code></li>\n<li>Direct Amount can also be entered based on Condtion. See example 3</li></ol>\n\n<h4>Examples</h4>\n<ol>\n<li>Calculating Basic Salary based on <code>base</code>\n<pre><code>Condition: base &lt; 10000</code></pre>\n<pre><code>Formula: base * .2</code></pre></li>\n<li>Calculating HRA based on Basic Salary<code>BS</code> \n<pre><code>Condition: BS &gt; 2000</code></pre>\n<pre><code>Formula: BS * .1</code></pre></li>\n<li>Calculating TDS based on Employment Type<code>employment_type</code> \n<pre><code>Condition: employment_type==\"Intern\"</code></pre>\n<pre><code>Amount: 1000</code></pre></li>\n</ol>"
   },
   {
+   "fieldname": "additional_salary",
+   "fieldtype": "Link",
+   "label": "Additional Salary ",
+   "options": "Additional Salary"
+  },
+  {
    "default": "0",
    "depends_on": "eval:doc.parentfield=='deductions'",
    "fetch_from": "salary_component.exempted_from_income_tax",
@@ -204,7 +211,7 @@
  ],
  "istable": 1,
  "links": [],
- "modified": "2020-04-24 20:00:16.475295",
+ "modified": "2020-04-04 20:00:16.475295",
  "modified_by": "Administrator",
  "module": "HR",
  "name": "Salary Detail",
@@ -213,4 +220,4 @@
  "quick_entry": 1,
  "sort_field": "modified",
  "sort_order": "DESC"
-}
\ No newline at end of file
+}
diff --git a/erpnext/hr/doctype/salary_slip/salary_slip.py b/erpnext/hr/doctype/salary_slip/salary_slip.py
index db93f31..4d5c843 100644
--- a/erpnext/hr/doctype/salary_slip/salary_slip.py
+++ b/erpnext/hr/doctype/salary_slip/salary_slip.py
@@ -66,7 +66,6 @@
 		else:
 			self.set_status()
 			self.update_status(self.name)
-			self.update_salary_slip_in_additional_salary()
 			self.make_loan_repayment_entry()
 			if (frappe.db.get_single_value("HR Settings", "email_salary_slip_to_employee")) and not frappe.flags.via_payroll_entry:
 				self.email_salary_slip()
@@ -74,7 +73,6 @@
 	def on_cancel(self):
 		self.set_status()
 		self.update_status()
-		self.update_salary_slip_in_additional_salary()
 		self.cancel_loan_repayment_entry()
 
 	def on_trash(self):
@@ -464,14 +462,15 @@
 						self.update_component_row(frappe._dict(last_benefit.struct_row), amount, "earnings")
 
 	def add_additional_salary_components(self, component_type):
-		additional_components = get_additional_salary_component(self.employee,
+		salary_components_details, additional_salary_details = get_additional_salary_component(self.employee,
 			self.start_date, self.end_date, component_type)
-		if additional_components:
-			for additional_component in additional_components:
-				amount = additional_component.amount
-				overwrite = additional_component.overwrite
-				self.update_component_row(frappe._dict(additional_component.struct_row), amount,
-					component_type, overwrite=overwrite)
+		if salary_components_details and additional_salary_details:
+			for additional_salary in additional_salary_details:
+				additional_salary =frappe._dict(additional_salary)
+				amount = additional_salary.amount
+				overwrite = additional_salary.overwrite
+				self.update_component_row(frappe._dict(salary_components_details[additional_salary.component]), amount,
+					component_type, overwrite=overwrite, additional_salary=additional_salary.name)
 
 	def add_tax_components(self, payroll_period):
 		# Calculate variable_based_on_taxable_salary after all components updated in salary slip
@@ -491,13 +490,12 @@
 			tax_row = self.get_salary_slip_row(d)
 			self.update_component_row(tax_row, tax_amount, "deductions")
 
-	def update_component_row(self, struct_row, amount, key, overwrite=1):
+	def update_component_row(self, struct_row, amount, key, overwrite=1, additional_salary = ''):
 		component_row = None
 		for d in self.get(key):
 			if d.salary_component == struct_row.salary_component:
 				component_row = d
-
-		if not component_row:
+		if not component_row or (struct_row.get("is_additional_component") and not overwrite):
 			if amount:
 				self.append(key, {
 					'amount': amount,
@@ -505,6 +503,7 @@
 					'depends_on_payment_days' : struct_row.depends_on_payment_days,
 					'salary_component' : struct_row.salary_component,
 					'abbr' : struct_row.abbr,
+					'additional_salary': additional_salary,
 					'do_not_include_in_total' : struct_row.do_not_include_in_total,
 					'is_tax_applicable': struct_row.is_tax_applicable,
 					'is_flexible_benefit': struct_row.is_flexible_benefit,
@@ -517,6 +516,7 @@
 			if struct_row.get("is_additional_component"):
 				if overwrite:
 					component_row.additional_amount = amount - component_row.get("default_amount", 0)
+					component_row.additional_salary = additional_salary
 				else:
 					component_row.additional_amount = amount
 
@@ -936,14 +936,6 @@
 				"repay_from_salary": 1,
 			})
 
-
-	def update_salary_slip_in_additional_salary(self):
-		salary_slip = self.name if self.docstatus==1 else None
-		frappe.db.sql("""
-			update `tabAdditional Salary` set salary_slip=%s
-			where employee=%s and payroll_date between %s and %s and docstatus=1
-		""", (salary_slip, self.employee, self.start_date, self.end_date))
-
 	def make_loan_repayment_entry(self):
 		for loan in self.loans:
 			repayment_entry = create_repayment_entry(loan.loan, self.employee,
diff --git a/erpnext/hr/doctype/salary_slip/test_salary_slip.py b/erpnext/hr/doctype/salary_slip/test_salary_slip.py
index fc687a3..a7dcb94 100644
--- a/erpnext/hr/doctype/salary_slip/test_salary_slip.py
+++ b/erpnext/hr/doctype/salary_slip/test_salary_slip.py
@@ -18,19 +18,7 @@
 
 class TestSalarySlip(unittest.TestCase):
 	def setUp(self):
-		make_earning_salary_component(setup=True, company_list=["_Test Company"])
-		make_deduction_salary_component(setup=True, company_list=["_Test Company"])
-
-		for dt in ["Leave Application", "Leave Allocation", "Salary Slip", "Attendance"]:
-			frappe.db.sql("delete from `tab%s`" % dt)
-
-		self.make_holiday_list()
-
-		frappe.db.set_value("Company", erpnext.get_default_company(), "default_holiday_list", "Salary Slip Test Holiday List")
-		frappe.db.set_value("HR Settings", None, "email_salary_slip_to_employee", 0)
-		frappe.db.set_value('HR Settings', None, 'leave_status_notification_template', None)
-		frappe.db.set_value('HR Settings', None, 'leave_approval_notification_template', None)
-		
+		setup_test()
 	def tearDown(self):
 		frappe.db.set_value("HR Settings", None, "include_holidays_in_total_working_days", 0)
 		frappe.set_user("Administrator")
@@ -374,19 +362,6 @@
 		# undelete fixture data
 		frappe.db.rollback()
 
-	def make_holiday_list(self):
-		fiscal_year = get_fiscal_year(nowdate(), company=erpnext.get_default_company())
-		if not frappe.db.get_value("Holiday List", "Salary Slip Test Holiday List"):
-			holiday_list = frappe.get_doc({
-				"doctype": "Holiday List",
-				"holiday_list_name": "Salary Slip Test Holiday List",
-				"from_date": fiscal_year[1],
-				"to_date": fiscal_year[2],
-				"weekly_off": "Sunday"
-			}).insert()
-			holiday_list.get_weekly_off_dates()
-			holiday_list.save()
-
 	def make_activity_for_employee(self):
 		activity_type = frappe.get_doc("Activity Type", "_Test Activity Type")
 		activity_type.billing_rate = 50
@@ -702,4 +677,31 @@
 		status = "Approved",
 		leave_approver = 'test@example.com'
 	))
-	leave_application.submit()
\ No newline at end of file
+	leave_application.submit()
+
+def setup_test():
+	make_earning_salary_component(setup=True, company_list=["_Test Company"])
+	make_deduction_salary_component(setup=True, company_list=["_Test Company"])
+
+	for dt in ["Leave Application", "Leave Allocation", "Salary Slip", "Attendance"]:
+		frappe.db.sql("delete from `tab%s`" % dt)
+
+	make_holiday_list()
+
+	frappe.db.set_value("Company", erpnext.get_default_company(), "default_holiday_list", "Salary Slip Test Holiday List")
+	frappe.db.set_value("HR Settings", None, "email_salary_slip_to_employee", 0)
+	frappe.db.set_value('HR Settings', None, 'leave_status_notification_template', None)
+	frappe.db.set_value('HR Settings', None, 'leave_approval_notification_template', None)
+
+def make_holiday_list():
+	fiscal_year = get_fiscal_year(nowdate(), company=erpnext.get_default_company())
+	if not frappe.db.get_value("Holiday List", "Salary Slip Test Holiday List"):
+		holiday_list = frappe.get_doc({
+			"doctype": "Holiday List",
+			"holiday_list_name": "Salary Slip Test Holiday List",
+			"from_date": fiscal_year[1],
+			"to_date": fiscal_year[2],
+			"weekly_off": "Sunday"
+		}).insert()
+		holiday_list.get_weekly_off_dates()
+		holiday_list.save()
diff --git a/erpnext/hr/report/monthly_attendance_sheet/monthly_attendance_sheet.js b/erpnext/hr/report/monthly_attendance_sheet/monthly_attendance_sheet.js
index 348c5e7..bd4ed3c 100644
--- a/erpnext/hr/report/monthly_attendance_sheet/monthly_attendance_sheet.js
+++ b/erpnext/hr/report/monthly_attendance_sheet/monthly_attendance_sheet.js
@@ -31,6 +31,18 @@
 			"options": "Company",
 			"default": frappe.defaults.get_user_default("Company"),
 			"reqd": 1
+		},
+		{
+			"fieldname":"group_by",
+			"label": __("Group By"),
+			"fieldtype": "Select",
+			"options": ["","Branch","Grade","Department","Designation"]
+		},
+		{
+			"fieldname":"summarized_view",
+			"label": __("Summarized View"),
+			"fieldtype": "Check",
+			"Default": 0,
 		}
 	],
 
diff --git a/erpnext/hr/report/monthly_attendance_sheet/monthly_attendance_sheet.py b/erpnext/hr/report/monthly_attendance_sheet/monthly_attendance_sheet.py
index 9a9e42e..d98ed1b 100644
--- a/erpnext/hr/report/monthly_attendance_sheet/monthly_attendance_sheet.py
+++ b/erpnext/hr/report/monthly_attendance_sheet/monthly_attendance_sheet.py
@@ -7,65 +7,127 @@
 from frappe import msgprint, _
 from calendar import monthrange
 
+status_map = {
+	"Absent": "A",
+	"Half Day": "HD",
+	"Holiday": "<b>H</b>",
+	"Weekly Off": "<b>WO</b>",
+	"On Leave": "L",
+	"Present": "P",
+	"Work From Home": "WFH"
+	}
+
+day_abbr = [
+	"Mon",
+	"Tue",
+	"Wed",
+	"Thu",
+	"Fri",
+	"Sat",
+	"Sun"
+]
+
 def execute(filters=None):
 	if not filters: filters = {}
 
 	conditions, filters = get_conditions(filters)
 	columns = get_columns(filters)
 	att_map = get_attendance_list(conditions, filters)
-	emp_map = get_employee_details(filters)
 
-	holiday_list = [emp_map[d]["holiday_list"] for d in emp_map if emp_map[d]["holiday_list"]]
+	if filters.group_by:
+		emp_map, group_by_parameters = get_employee_details(filters.group_by, filters.company)
+		holiday_list = []
+		for parameter in group_by_parameters:
+			h_list = [emp_map[parameter][d]["holiday_list"] for d in emp_map[parameter] if emp_map[parameter][d]["holiday_list"]]
+			holiday_list += h_list
+	else:
+		emp_map = get_employee_details(filters.group_by, filters.company)
+		holiday_list = [emp_map[d]["holiday_list"] for d in emp_map if emp_map[d]["holiday_list"]]
+
+
 	default_holiday_list = frappe.get_cached_value('Company',  filters.get("company"),  "default_holiday_list")
 	holiday_list.append(default_holiday_list)
 	holiday_list = list(set(holiday_list))
 	holiday_map = get_holiday(holiday_list, filters["month"])
 
 	data = []
-	leave_types = frappe.db.sql("""select name from `tabLeave Type`""", as_list=True)
-	leave_list = [d[0] for d in leave_types]
-	columns.extend(leave_list)
-	columns.extend([_("Total Late Entries") + ":Float:120", _("Total Early Exits") + ":Float:120"])
 
-	for emp in sorted(att_map):
-		emp_det = emp_map.get(emp)
-		if not emp_det:
+	leave_list = None
+	if filters.summarized_view:
+		leave_types = frappe.db.sql("""select name from `tabLeave Type`""", as_list=True)
+		leave_list = [d[0] + ":Float:120" for d in leave_types]
+		columns.extend(leave_list)
+		columns.extend([_("Total Late Entries") + ":Float:120", _("Total Early Exits") + ":Float:120"])
+
+	if filters.group_by:
+		for parameter in group_by_parameters:
+			data.append([ "<b>"+ parameter + "</b>"])
+			record = add_data(emp_map[parameter], att_map, filters, holiday_map, conditions, leave_list=leave_list)
+			data += record
+	else:
+		record = add_data(emp_map, att_map, filters, holiday_map, conditions, leave_list=leave_list)
+		data += record
+
+	return columns, data
+
+
+def add_data(employee_map, att_map, filters, holiday_map, conditions, leave_list=None):
+
+	record = []
+	for emp in employee_map:
+		emp_det = employee_map.get(emp)
+		if not emp_det or emp not in att_map:
 			continue
 
-		row = [emp, emp_det.employee_name, emp_det.branch, emp_det.department, emp_det.designation,
-			emp_det.company]
+		row = []
+		if filters.group_by:
+			row += [" "]
+		row += [emp, emp_det.employee_name]
 
-		total_p = total_a = total_l = 0.0
+		total_p = total_a = total_l = total_h = total_um= 0.0
 		for day in range(filters["total_days_in_month"]):
+			status = None
 			status = att_map.get(emp).get(day + 1)
-			status_map = {
-				"Absent": "A",
-				"Half Day": "HD",
-				"Holiday":"<b>H</b>",
-				"On Leave": "L",
-				"Present": "P",
-				"Work From Home": "WFH"
-			}
 
 			if status is None and holiday_map:
 				emp_holiday_list = emp_det.holiday_list if emp_det.holiday_list else default_holiday_list
-				if emp_holiday_list in holiday_map and (day+1) in holiday_map[emp_holiday_list]:
-					status = "Holiday"
 
-			row.append(status_map.get(status, ""))
+				if emp_holiday_list in holiday_map:
+					for idx, ele in enumerate(holiday_map[emp_holiday_list]):
+						if day+1 == holiday_map[emp_holiday_list][idx][0]:
+							if holiday_map[emp_holiday_list][idx][1]:
+								status = "Weekly Off"
+							else:
+								status = "Holiday"
+							total_h += 1
 
-			if status == "Present":
-				total_p += 1
-			elif status == "Absent":
-				total_a += 1
-			elif status == "On Leave":
-				total_l += 1
-			elif status == "Half Day":
-				total_p += 0.5
-				total_a += 0.5
-				total_l += 0.5
 
-		row += [total_p, total_l, total_a]
+				# if emp_holiday_list in holiday_map and (day+1) in holiday_map[emp_holiday_list][0]:
+				# 	if holiday_map[emp_holiday_list][1]:
+				# 		status= "Weekly Off"
+				# 	else:
+				# 		status = "Holiday"
+
+				# 	 += 1
+
+			if not filters.summarized_view:
+				row.append(status_map.get(status, ""))
+			else:
+				if status == "Present":
+					total_p += 1
+				elif status == "Absent":
+					total_a += 1
+				elif status == "On Leave":
+					total_l += 1
+				elif status == "Half Day":
+					total_p += 0.5
+					total_a += 0.5
+					total_l += 0.5
+				elif not status:
+					total_um += 1
+
+		if filters.summarized_view:
+			row += [total_p, total_l, total_a, total_h, total_um]
 
 		if not filters.get("employee"):
 			filters.update({"employee": emp})
@@ -73,43 +135,53 @@
 		elif not filters.get("employee") == emp:
 			filters.update({"employee": emp})
 
-		leave_details = frappe.db.sql("""select leave_type, status, count(*) as count from `tabAttendance`\
-			where leave_type is not NULL %s group by leave_type, status""" % conditions, filters, as_dict=1)
+		if filters.summarized_view:
+			leave_details = frappe.db.sql("""select leave_type, status, count(*) as count from `tabAttendance`\
+				where leave_type is not NULL %s group by leave_type, status""" % conditions, filters, as_dict=1)
 
-		time_default_counts = frappe.db.sql("""select (select count(*) from `tabAttendance` where \
-			late_entry = 1 %s) as late_entry_count, (select count(*) from tabAttendance where \
-			early_exit = 1 %s) as early_exit_count""" % (conditions, conditions), filters)
+			time_default_counts = frappe.db.sql("""select (select count(*) from `tabAttendance` where \
+				late_entry = 1 %s) as late_entry_count, (select count(*) from tabAttendance where \
+				early_exit = 1 %s) as early_exit_count""" % (conditions, conditions), filters)
 
-		leaves = {}
-		for d in leave_details:
-			if d.status == "Half Day":
-				d.count = d.count * 0.5
-			if d.leave_type in leaves:
-				leaves[d.leave_type] += d.count
-			else:
-				leaves[d.leave_type] = d.count
+			leaves = {}
+			for d in leave_details:
+				if d.status == "Half Day":
+					d.count = d.count * 0.5
+				if d.leave_type in leaves:
+					leaves[d.leave_type] += d.count
+				else:
+					leaves[d.leave_type] = d.count
 
-		for d in leave_list:
-			if d in leaves:
-				row.append(leaves[d])
-			else:
-				row.append("0.0")
+			for d in leave_list:
+				if d in leaves:
+					row.append(leaves[d])
+				else:
+					row.append("0.0")
 
-		row.extend([time_default_counts[0][0],time_default_counts[0][1]])
-		data.append(row)
-	return columns, data
+			row.extend([time_default_counts[0][0],time_default_counts[0][1]])
+		record.append(row)
+
+
+	return record
 
 def get_columns(filters):
-	columns = [
-		_("Employee") + ":Link/Employee:120", _("Employee Name") + "::140", _("Branch")+ ":Link/Branch:120",
-		_("Department") + ":Link/Department:120", _("Designation") + ":Link/Designation:120",
-		 _("Company") + ":Link/Company:120"
+
+	columns = []
+
+	if filters.group_by:
+		columns = [_(filters.group_by)+ ":Link/Branch:120"]
+
+	columns += [
+		_("Employee") + ":Link/Employee:120", _("Employee Name") + ":Link/Employee:120"
 	]
 
-	for day in range(filters["total_days_in_month"]):
-		columns.append(cstr(day+1) +"::20")
-
-	columns += [_("Total Present") + ":Float:80", _("Total Leaves") + ":Float:80",  _("Total Absent") + ":Float:80"]
+	if not filters.summarized_view:
+		for day in range(filters["total_days_in_month"]):
+			date = str(filters.year) + "-" + str(filters.month)+ "-" + str(day+1)
+			day_name = day_abbr[getdate(date).weekday()]
+			columns.append(cstr(day+1)+ " " +day_name +"::65")
+	else:
+		columns += [_("Total Present") + ":Float:120", _("Total Leaves") + ":Float:120",  _("Total Absent") + ":Float:120", _("Total Holidays") + ":Float:120", _("Unmarked Days")+ ":Float:120"]
 	return columns
 
 def get_attendance_list(conditions, filters):
@@ -140,19 +212,43 @@
 
 	return conditions, filters
 
-def get_employee_details(filters):
-	emp_map = frappe._dict()
-	for d in frappe.db.sql("""select name, employee_name, designation, department, branch, company,
-		holiday_list from tabEmployee where company = %s""", (filters.get("company")), as_dict=1):
-		emp_map.setdefault(d.name, d)
+def get_employee_details(group_by, company):
+	emp_map = {}
+	query = """select name, employee_name, designation, department, branch, company,
+		holiday_list from `tabEmployee` where company = '%s' """ % frappe.db.escape(company)
 
-	return emp_map
+	if group_by:
+		group_by = group_by.lower()
+		query += " order by " + group_by + " ASC"
+
+	employee_details = frappe.db.sql(query , as_dict=1)
+
+	group_by_parameters = []
+	if group_by:
+
+		group_by_parameters = list(set(detail.get(group_by, "") for detail in employee_details if detail.get(group_by, "")))
+		for parameter in group_by_parameters:
+				emp_map[parameter] = {}
+
+
+	for d in employee_details:
+		if group_by and len(group_by_parameters):
+			if d.get(group_by, None):
+
+				emp_map[d.get(group_by)][d.name] = d
+		else:
+			emp_map[d.name] = d
+
+	if not group_by:
+		return emp_map
+	else:
+		return emp_map, group_by_parameters
 
 def get_holiday(holiday_list, month):
 	holiday_map = frappe._dict()
 	for d in holiday_list:
 		if d:
-			holiday_map.setdefault(d, frappe.db.sql_list('''select day(holiday_date) from `tabHoliday`
+			holiday_map.setdefault(d, frappe.db.sql('''select day(holiday_date), weekly_off from `tabHoliday`
 				where parent=%s and month(holiday_date)=%s''', (d, month)))
 
 	return holiday_map
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index 5295399..ba17b67 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -630,7 +630,7 @@
 execute:frappe.reload_doc('desk', 'doctype', 'dashboard_chart_source')
 execute:frappe.reload_doc('desk', 'doctype', 'dashboard_chart')
 execute:frappe.reload_doc('desk', 'doctype', 'dashboard_chart_field')
-erpnext.patches.v12_0.add_default_dashboards
+erpnext.patches.v12_0.add_default_dashboards # 2020-04-05
 erpnext.patches.v12_0.remove_bank_remittance_custom_fields
 erpnext.patches.v12_0.generate_leave_ledger_entries
 execute:frappe.delete_doc_if_exists("Report", "Loan Repayment")
@@ -662,6 +662,7 @@
 erpnext.patches.v12_0.move_bank_account_swift_number_to_bank
 erpnext.patches.v12_0.rename_bank_reconciliation
 erpnext.patches.v12_0.rename_bank_reconciliation_fields # 2020-01-22
+erpnext.patches.v12_0.set_purchase_receipt_delivery_note_detail
 erpnext.patches.v12_0.add_permission_in_lower_deduction
 erpnext.patches.v12_0.set_received_qty_in_material_request_as_per_stock_uom
 erpnext.patches.v12_0.rename_account_type_doctype
@@ -677,3 +678,4 @@
 erpnext.patches.v12_0.fix_quotation_expired_status
 erpnext.patches.v12_0.update_appointment_reminder_scheduler_entry
 erpnext.patches.v12_0.retain_permission_rules_for_video_doctype
+erpnext.patches.v13_0.patch_to_fix_reverse_linking_in_additional_salary_encashment_and_incentive
diff --git a/erpnext/patches/v11_0/add_permissions_in_gst_settings.py b/erpnext/patches/v11_0/add_permissions_in_gst_settings.py
index d793611..83b2a4c 100644
--- a/erpnext/patches/v11_0/add_permissions_in_gst_settings.py
+++ b/erpnext/patches/v11_0/add_permissions_in_gst_settings.py
@@ -7,4 +7,5 @@
 		return
 
 	frappe.reload_doc("regional", "doctype", "lower_deduction_certificate")
-	add_permissions()
\ No newline at end of file
+	frappe.reload_doc("regional", "doctype", "gstr_3b_report")
+	add_permissions()
diff --git a/erpnext/patches/v12_0/add_default_dashboards.py b/erpnext/patches/v12_0/add_default_dashboards.py
index 0c3f2f8..24661cc 100644
--- a/erpnext/patches/v12_0/add_default_dashboards.py
+++ b/erpnext/patches/v12_0/add_default_dashboards.py
@@ -6,4 +6,5 @@
 
 def execute():
 	frappe.reload_doc("desk", "doctype", "number_card_link")
+	frappe.reload_doc("desk", "doctype", "patient_appointment")
 	add_dashboards()
diff --git a/erpnext/patches/v12_0/set_purchase_receipt_delivery_note_detail.py b/erpnext/patches/v12_0/set_purchase_receipt_delivery_note_detail.py
new file mode 100644
index 0000000..f5bd8c3
--- /dev/null
+++ b/erpnext/patches/v12_0/set_purchase_receipt_delivery_note_detail.py
@@ -0,0 +1,84 @@
+from __future__ import unicode_literals
+import frappe
+from collections import defaultdict
+
+def execute():
+	def map_rows(doc_row, return_doc_row, detail_field, doctype):
+		"""Map rows after identifying similar ones."""
+
+		frappe.db.sql(""" UPDATE `tab{doctype} Item` set {detail_field} = '{doc_row_name}'
+				where name = '{return_doc_row_name}'""" \
+			.format(doctype=doctype,
+					detail_field=detail_field,
+					doc_row_name=doc_row.get('name'),
+					return_doc_row_name=return_doc_row.get('name'))) #nosec
+
+	def row_is_mappable(doc_row, return_doc_row, detail_field):
+		"""Checks if two rows are similar enough to be mapped."""
+
+		if doc_row.item_code == return_doc_row.item_code and not return_doc_row.get(detail_field):
+			if doc_row.get('batch_no') and return_doc_row.get('batch_no') and doc_row.batch_no == return_doc_row.batch_no:
+				return True
+
+			elif doc_row.get('serial_no') and return_doc_row.get('serial_no'):
+				doc_sn = doc_row.serial_no.split('\n')
+				return_doc_sn = return_doc_row.serial_no.split('\n')
+
+				if set(doc_sn) & set(return_doc_sn):
+					# if two rows have serial nos in common, map them
+					return True
+
+			elif doc_row.rate == return_doc_row.rate:
+				return True
+		else:
+			return False
+
+	def make_return_document_map(doctype, return_document_map):
+		"""Returns a map of documents and it's return documents.
+		Format => { 'document' : ['return_document_1','return_document_2'] }"""
+
+		return_against_documents = frappe.db.sql("""
+			SELECT
+				return_against as document, name as return_document
+			FROM `tab{doctype}`
+			WHERE
+				is_return = 1 and docstatus = 1""".format(doctype=doctype),as_dict=1) #nosec
+
+		for entry in return_against_documents:
+			return_document_map[entry.document].append(entry.return_document)
+
+		return return_document_map
+
+	def set_document_detail_in_return_document(doctype):
+		"""Map each row of the original document in the return document."""
+		mapped = []
+		return_document_map = defaultdict(list)
+		detail_field = "purchase_receipt_item" if doctype=="Purchase Receipt" else "dn_detail"
+
+		child_doc = frappe.scrub("{0} Item".format(doctype))
+		frappe.reload_doc("stock", "doctype", child_doc)
+
+		return_document_map = make_return_document_map(doctype, return_document_map)
+
+		#iterate through original documents and its return documents
+		for docname in return_document_map:
+			doc_items = frappe.get_doc(doctype, docname).get("items")
+			for return_doc in return_document_map[docname]:
+				return_doc_items = frappe.get_doc(doctype, return_doc).get("items")
+
+				#iterate through return document items and original document items for mapping
+				for return_item in return_doc_items:
+					for doc_item in doc_items:
+						if row_is_mappable(doc_item, return_item, detail_field) and doc_item.get('name') not in mapped:
+							map_rows(doc_item, return_item, detail_field, doctype)
+							mapped.append(doc_item.get('name'))
+							break
+						else:
+							continue
+
+	set_document_detail_in_return_document("Purchase Receipt")
+	set_document_detail_in_return_document("Delivery Note")
+	frappe.db.commit()
+
+
+
diff --git a/erpnext/patches/v13_0/patch_to_fix_reverse_linking_in_additional_salary_encashment_and_incentive.py b/erpnext/patches/v13_0/patch_to_fix_reverse_linking_in_additional_salary_encashment_and_incentive.py
new file mode 100644
index 0000000..ddcadcb
--- /dev/null
+++ b/erpnext/patches/v13_0/patch_to_fix_reverse_linking_in_additional_salary_encashment_and_incentive.py
@@ -0,0 +1,52 @@
+from __future__ import unicode_literals
+
+import frappe
+
+def execute():
+	if not frappe.db.table_exists("Additional Salary"):
+		return
+
+	for doctype in ("Additional Salary", "Leave Encashment", "Employee Incentive", "Salary Detail"):
+		frappe.reload_doc("hr", "doctype", doctype)
+
+	additional_salaries = frappe.get_all("Additional Salary",
+		fields = ['name', "salary_slip", "type", "salary_component"],
+		filters = {'salary_slip': ['!=', '']},
+		group_by = 'salary_slip'
+	)
+	leave_encashments = frappe.get_all("Leave Encashment",
+		fields = ["name","additional_salary"],
+		filters = {'additional_salary': ['!=', '']}
+	)
+	employee_incentives = frappe.get_all("Employee Incentive",
+		fields= ["name", "additional_salary"],
+		filters = {'additional_salary': ['!=', '']}
+	)
+
+	for incentive in employee_incentives:
+		frappe.db.sql(""" UPDATE `tabAdditional Salary`
+			SET ref_doctype = 'Employee Incentive', ref_docname = %s
+			WHERE name = %s
+		""", (incentive['name'], incentive['additional_salary']))
+
+
+	for leave_encashment in leave_encashments:
+		frappe.db.sql(""" UPDATE `tabAdditional Salary`
+			SET ref_doctype = 'Leave Encashment', ref_docname = %s
+			WHERE name = %s
+		""", (leave_encashment['name'], leave_encashment['additional_salary']))
+
+	salary_slips = [sal["salary_slip"] for sal in additional_salaries]
+
+	for salary in additional_salaries:
+		comp_type = "earnings" if salary['type'] == 'Earning' else 'deductions'
+		if salary["salary_slip"] and salary_slips.count(salary["salary_slip"]) == 1:
+			frappe.db.sql("""
+				UPDATE `tabSalary Detail`
+				SET additional_salary = %s
+				WHERE parenttype = 'Salary Slip'
+					and parentfield = %s
+					and parent = %s
+					and salary_component = %s
+			""", (salary["name"], comp_type, salary["salary_slip"], salary["salary_component"]))
+
diff --git a/erpnext/setup/setup_wizard/data/dashboard_charts.py b/erpnext/setup/setup_wizard/data/dashboard_charts.py
index bb8c131..b182dfc 100644
--- a/erpnext/setup/setup_wizard/data/dashboard_charts.py
+++ b/erpnext/setup/setup_wizard/data/dashboard_charts.py
@@ -29,7 +29,8 @@
 					{ "chart": "Incoming Bills (Purchase Invoice)" },
 					{ "chart": "Bank Balance" },
 					{ "chart": "Income" },
-					{ "chart": "Expenses" }
+					{ "chart": "Expenses" },
+					{ "chart": "Patient Appointments" }
 				]
 			}
 		],
@@ -107,6 +108,21 @@
 				"document_type": "Sales Invoice",
 				"type": "Bar",
 				"width": "Half"
+			},
+			{
+				"doctype": "Dashboard Chart",
+				"time_interval": "Daily",
+				"chart_name": "Patient Appointments",
+				"timespan": "Last Month",
+				"color": "#77ecca",
+				"filters_json": json.dumps({}),
+				"chart_type": "Count",
+				"timeseries": 1,
+				"based_on": "appointment_datetime",
+				"owner": "Administrator",
+				"document_type": "Patient Appointment",
+				"type": "Line",
+				"width": "Half"
 			}
 		]
 	}
diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.py b/erpnext/stock/doctype/delivery_note/delivery_note.py
index 37f9097..d04cf78 100644
--- a/erpnext/stock/doctype/delivery_note/delivery_note.py
+++ b/erpnext/stock/doctype/delivery_note/delivery_note.py
@@ -388,13 +388,12 @@
 
 def get_returned_qty_map(delivery_note):
 	"""returns a map: {so_detail: returned_qty}"""
-	returned_qty_map = frappe._dict(frappe.db.sql("""select dn_item.item_code, sum(abs(dn_item.qty)) as qty
+	returned_qty_map = frappe._dict(frappe.db.sql("""select dn_item.dn_detail, abs(dn_item.qty) as qty
 		from `tabDelivery Note Item` dn_item, `tabDelivery Note` dn
 		where dn.name = dn_item.parent
 			and dn.docstatus = 1
 			and dn.is_return = 1
 			and dn.return_against = %s
-		group by dn_item.item_code
 	""", delivery_note))
 
 	return returned_qty_map
@@ -413,7 +412,7 @@
 		target.run_method("set_po_nos")
 
 		if len(target.get("items")) == 0:
-			frappe.throw(_("All these items have already been invoiced"))
+			frappe.throw(_("All these items have already been Invoiced/Returned"))
 
 		target.run_method("calculate_taxes_and_totals")
 
@@ -438,9 +437,9 @@
 		pending_qty = item_row.qty - invoiced_qty_map.get(item_row.name, 0)
 
 		returned_qty = 0
-		if returned_qty_map.get(item_row.item_code, 0) > 0:
-			returned_qty = flt(returned_qty_map.get(item_row.item_code, 0))
-			returned_qty_map[item_row.item_code] -= pending_qty
+		if returned_qty_map.get(item_row.name, 0) > 0:
+			returned_qty = flt(returned_qty_map.get(item_row.name, 0))
+			returned_qty_map[item_row.name] -= pending_qty
 
 		if returned_qty:
 			if returned_qty >= pending_qty:
diff --git a/erpnext/stock/doctype/delivery_note/test_delivery_note.py b/erpnext/stock/doctype/delivery_note/test_delivery_note.py
index bf7007a..a921a56 100644
--- a/erpnext/stock/doctype/delivery_note/test_delivery_note.py
+++ b/erpnext/stock/doctype/delivery_note/test_delivery_note.py
@@ -612,6 +612,7 @@
 		dn1 = create_delivery_note(is_return=1, return_against=dn.name, qty=-1, do_not_submit=True)
 		dn1.items[0].against_sales_order = so.name
 		dn1.items[0].so_detail = so.items[0].name
+		dn1.items[0].dn_detail = dn.items[0].name
 		dn1.submit()
 
 		si = make_sales_invoice(dn.name)
@@ -638,7 +639,9 @@
 		si1.save()
 		si1.submit()
 
-		create_delivery_note(is_return=1, return_against=dn.name, qty=-2)
+		dn1 = create_delivery_note(is_return=1, return_against=dn.name, qty=-2, do_not_submit=True)
+		dn1.items[0].dn_detail = dn.items[0].name
+		dn1.submit()
 
 		si2 = make_sales_invoice(dn.name)
 		self.assertEquals(si2.items[0].qty, 2)
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 782ac84..7ea2de2 100644
--- a/erpnext/stock/doctype/delivery_note_item/delivery_note_item.json
+++ b/erpnext/stock/doctype/delivery_note_item/delivery_note_item.json
@@ -67,6 +67,7 @@
   "so_detail",
   "against_sales_invoice",
   "si_detail",
+  "dn_detail",
   "section_break_40",
   "batch_no",
   "serial_no",
@@ -699,6 +700,15 @@
   {
    "fieldname": "dimension_col_break",
    "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "dn_detail",
+   "fieldtype": "Data",
+   "hidden": 1,
+   "label": "Against Delivery Note Item",
+   "no_copy": 1,
+   "print_hide": 1,
+   "read_only": 1
   }
  ],
  "idx": 1,
diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
index 8dfe1d1..e6ab8d6 100644
--- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
+++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
@@ -504,7 +504,7 @@
 
 	def set_missing_values(source, target):
 		if len(target.get("items")) == 0:
-			frappe.throw(_("All items have already been invoiced"))
+			frappe.throw(_("All items have already been Invoiced/Returned"))
 
 		doc = frappe.get_doc(target)
 		doc.ignore_pricing_rule = 1
@@ -514,11 +514,11 @@
 
 	def update_item(source_doc, target_doc, source_parent):
 		target_doc.qty, returned_qty = get_pending_qty(source_doc)
-		returned_qty_map[source_doc.item_code] = returned_qty
+		returned_qty_map[source_doc.name] = returned_qty
 
 	def get_pending_qty(item_row):
 		pending_qty = item_row.qty - invoiced_qty_map.get(item_row.name, 0)
-		returned_qty = flt(returned_qty_map.get(item_row.item_code, 0))
+		returned_qty = flt(returned_qty_map.get(item_row.name, 0))
 		if returned_qty:
 			if returned_qty >= pending_qty:
 				pending_qty = 0
@@ -576,13 +576,12 @@
 
 def get_returned_qty_map(purchase_receipt):
 	"""returns a map: {so_detail: returned_qty}"""
-	returned_qty_map = frappe._dict(frappe.db.sql("""select pr_item.item_code, sum(abs(pr_item.qty)) as qty
+	returned_qty_map = frappe._dict(frappe.db.sql("""select pr_item.purchase_receipt_item, abs(pr_item.qty) as qty
 		from `tabPurchase Receipt Item` pr_item, `tabPurchase Receipt` pr
 		where pr.name = pr_item.parent
 			and pr.docstatus = 1
 			and pr.is_return = 1
 			and pr.return_against = %s
-		group by pr_item.item_code
 	""", purchase_receipt))
 
 	return returned_qty_map
diff --git a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py
index 3d42590..649cfdc 100644
--- a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py
+++ b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py
@@ -475,6 +475,7 @@
 		pr1 = make_purchase_receipt(is_return=1, return_against=pr.name, qty=-1, do_not_submit=True)
 		pr1.items[0].purchase_order = po.name
 		pr1.items[0].purchase_order_item = po.items[0].name
+		pr1.items[0].purchase_receipt_item = pr.items[0].name
 		pr1.submit()
 
 		pi = make_purchase_invoice(pr.name)
@@ -498,7 +499,9 @@
 		pi1.save()
 		pi1.submit()
 
-		make_purchase_receipt(is_return=1, return_against=pr1.name, qty=-2)
+		pr2 = make_purchase_receipt(is_return=1, return_against=pr1.name, qty=-2, do_not_submit=True)
+		pr2.items[0].purchase_receipt_item = pr1.items[0].name
+		pr2.submit()
 
 		pi2 = make_purchase_invoice(pr1.name)
 		self.assertEquals(pi2.items[0].qty, 2)
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 bc6bce9..c1e1f90 100644
--- a/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json
+++ b/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json
@@ -71,6 +71,7 @@
   "quality_inspection",
   "purchase_order_item",
   "material_request_item",
+  "purchase_receipt_item",
   "section_break_45",
   "allow_zero_valuation_rate",
   "bom",
@@ -821,6 +822,15 @@
    "options": "Warehouse"
   },
   {
+   "fieldname": "purchase_receipt_item",
+   "fieldtype": "Data",
+   "hidden": 1,
+   "label": "Purchase Receipt Item",
+   "no_copy": 1,
+   "print_hide": 1,
+   "read_only": 1
+  },
+  {
    "collapsible": 1,
    "fieldname": "image_column",
    "fieldtype": "Column Break"
@@ -829,7 +839,7 @@
  "idx": 1,
  "istable": 1,
  "links": [],
- "modified": "2020-04-10 19:01:21.154963",
+ "modified": "2020-04-28 19:01:21.154963",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Purchase Receipt Item",
diff --git a/erpnext/tests/test_search.py b/erpnext/tests/test_search.py
index b9665db..566495f 100644
--- a/erpnext/tests/test_search.py
+++ b/erpnext/tests/test_search.py
@@ -4,11 +4,13 @@
 from frappe.contacts.address_and_contact import filter_dynamic_link_doctypes
 
 class TestSearch(unittest.TestCase):
-	#Search for the word "cond", part of the word "conduire" (Lead) in french.
+	# Search for the word "cond", part of the word "conduire" (Lead) in french.
 	def test_contact_search_in_foreign_language(self):
 		frappe.local.lang = 'fr'
-		output = filter_dynamic_link_doctypes("DocType", "prospect", "name", 0, 20, {'fieldtype': 'HTML', 'fieldname': 'contact_html'})
-
+		output = filter_dynamic_link_doctypes("DocType", "cond", "name", 0, 20, {
+			'fieldtype': 'HTML',
+			'fieldname': 'contact_html'
+		})
 		result = [['found' for x in y if x=="Lead"] for y in output]
 		self.assertTrue(['found'] in result)