Salary Slip tests for tax calc on benefits, additional salary (#14985)

* tests for tax calc on benefits, additional salary

* fix tests - remove created additional salary
diff --git a/erpnext/hr/doctype/salary_slip/test_salary_slip.py b/erpnext/hr/doctype/salary_slip/test_salary_slip.py
index f4dbec7..9acb309 100644
--- a/erpnext/hr/doctype/salary_slip/test_salary_slip.py
+++ b/erpnext/hr/doctype/salary_slip/test_salary_slip.py
@@ -174,52 +174,87 @@
 		payroll_period = create_payroll_period()
 		create_tax_slab(payroll_period)
 		employee = make_employee("test_tax@salary.slip")
-		frappe.db.sql("""delete from `tabSalary Slip` where employee=%s""", (employee))
-		frappe.db.sql("""delete from `tabEmployee Tax Exemption Declaration` where employee=%s""", (employee))
-		frappe.db.sql("""delete from `tabEmployee Tax Exemption Proof Submission` where employee=%s""", (employee))
-		from erpnext.hr.doctype.salary_structure.test_salary_structure import make_salary_structure, create_salary_structure_assignment
-		salary_structure = make_salary_structure("Stucture to test tax", "Monthly", test_tax=True)
-		create_salary_structure_assignment(employee, salary_structure.name, payroll_period.start_date)
+		delete_docs = ["Salary Slip", "Additional Salary",
+						"Employee Tax Exemption Declaration",
+						"Employee Tax Exemption Proof Submission",
+						"Employee Benefit Claim", "Salary Structure Assignment"]
+		for doc in delete_docs:
+			frappe.db.sql("delete from `tab%s` where employee='%s'" % (doc, employee))
 
-		# create salary slip for whole period deducting tax only on last period to find the total tax amount paid
-		create_salary_slips_for_payroll_period(employee, salary_structure.name, payroll_period)
-		tax_paid_amount = frappe.db.sql("""select sum(sd.amount) from `tabSalary Detail` sd join `tabSalary Slip` ss where
-		ss.name=sd.parent and ss.employee=%s and ss.docstatus=1 and sd.salary_component='TDS'""", (employee))
+		from erpnext.hr.doctype.salary_structure.test_salary_structure import \
+			make_salary_structure, create_salary_structure_assignment
+		salary_structure = make_salary_structure("Stucture to test tax", "Monthly",
+			other_details={"max_benefits": 100000}, test_tax=True)
+		create_salary_structure_assignment(employee, salary_structure.name,
+			payroll_period.start_date)
 
-		# total taxable income 236000, at 5% tax slab
-		annual_tax = 11800
-		self.assertEqual(tax_paid_amount[0][0], annual_tax)
+		# create salary slip for whole period deducting tax only on last period
+		# to find the total tax amount paid
+		create_salary_slips_for_payroll_period(employee, salary_structure.name,
+			payroll_period, deduct_random=False)
+		tax_paid = get_tax_paid_in_period(employee)
+
+		# total taxable income 586000, 250000 @ 5%, 86000 @ 20% ie. 12500 + 17200
+		annual_tax = 29700
+		try:
+			self.assertEqual(tax_paid, annual_tax)
+		except AssertionError:
+			print("\nSalary Slip - Annual tax calculation failed\n")
+			raise
 		frappe.db.sql("""delete from `tabSalary Slip` where employee=%s""", (employee))
 
 		# create exemption declaration so the tax amount varies
 		create_exemption_declaration(employee, payroll_period.name)
 
 		# create for payroll deducting in random months
-		data["deducted_dates"] = create_salary_slips_for_payroll_period(employee, salary_structure.name, payroll_period, deduct_random=True)
-		tax_paid_amount = frappe.db.sql("""select sum(sd.amount) from `tabSalary Detail` sd join `tabSalary Slip` ss where
-		ss.name=sd.parent and ss.employee=%s and ss.docstatus=1 and sd.salary_component='TDS'""", (employee))
+		data["deducted_dates"] = create_salary_slips_for_payroll_period(employee,
+			salary_structure.name, payroll_period)
+		tax_paid = get_tax_paid_in_period(employee)
 
-		# No proof sumitted, total tax paid, should not change
+		# No proof, benefit claim sumitted, total tax paid, should not change
 		try:
-			self.assertEqual(tax_paid_amount[0][0], annual_tax)
+			self.assertEqual(tax_paid, annual_tax)
 		except AssertionError:
-			print("\nTax calculation failed on following case\n", data, "\n")
+			print("\nSalary Slip - Tax calculation failed on following case\n", data, "\n")
 			raise
 
-		# Submit proof for total 86000
-		data["proof"] = [create_proof_submission(employee, payroll_period, 50000), 50000]
-		data["proof1"] = [create_proof_submission(employee, payroll_period, 36000), 36000]
+		# Submit proof for total 120000
+		data["proof-1"] = create_proof_submission(employee, payroll_period, 50000)
+		data["proof-2"] = create_proof_submission(employee, payroll_period, 70000)
+
+		# Submit benefit claim for total 50000
+		data["benefit-1"] = create_benefit_claim(employee, payroll_period, 15000, "Medical Allowance")
+		data["benefit-2"] = create_benefit_claim(employee, payroll_period, 35000, "Leave Travel Allowance")
+
+
 		frappe.db.sql("""delete from `tabSalary Slip` where employee=%s""", (employee))
-		data["deducted_dates"] = create_salary_slips_for_payroll_period(employee, salary_structure.name, payroll_period, deduct_random=True)
-		tax_paid_amount = frappe.db.sql("""select sum(sd.amount) from `tabSalary Detail` sd join `tabSalary Slip` ss where
-		ss.name=sd.parent and ss.employee=%s and ss.docstatus=1 and sd.salary_component='TDS'""", (employee))
-		# total taxable income 150000, at 5% tax slab
+		data["deducted_dates"] = create_salary_slips_for_payroll_period(employee,
+			salary_structure.name, payroll_period)
+		tax_paid = get_tax_paid_in_period(employee)
+
+		# total taxable income 416000, 166000 @ 5% ie. 8300
 		try:
-			self.assertEqual(tax_paid_amount[0][0], 7500)
+			self.assertEqual(tax_paid, 8300)
 		except AssertionError:
-			print("\nTax calculation failed on following case\n", data, "\n")
+			print("\nSalary Slip - Tax calculation failed on following case\n", data, "\n")
 			raise
 
+		# create additional salary of 150000
+		frappe.db.sql("""delete from `tabSalary Slip` where employee=%s""", (employee))
+		data["additional-1"] = create_additional_salary(employee, payroll_period, 50000)
+		data["additional-2"] = create_additional_salary(employee, payroll_period, 100000)
+		data["deducted_dates"] = create_salary_slips_for_payroll_period(employee,
+			salary_structure.name, payroll_period)
+
+		# total taxable income 566000, 250000 @ 5%, 66000 @ 20%, 12500 + 13200
+		tax_paid = get_tax_paid_in_period(employee)
+		try:
+			self.assertEqual(tax_paid, 25700)
+		except AssertionError:
+			print("\nSalary Slip - Tax calculation failed on following case\n", data, "\n")
+			raise
+		frappe.db.sql("""delete from `tabAdditional Salary` where employee=%s""", (employee))
+
 	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"):
@@ -334,6 +369,31 @@
 				"type": "Earning"
 			}
 		]
+	if test_tax:
+		data.extend([
+						{
+							"salary_component": "Leave Travel Allowance",
+							"abbr": 'B',
+							"is_flexible_benefit": 1,
+							"type": "Earning",
+							"pay_against_benefit_claim": 1,
+							"max_benefit_amount": 100000
+						},
+						{
+							"salary_component": "Medical Allowance",
+							"abbr": 'B',
+							"is_flexible_benefit": 1,
+							"pay_against_benefit_claim": 0,
+							"type": "Earning",
+							"max_benefit_amount": 15000
+						},
+						{
+							"salary_component": "Perfomance Bonus",
+							"abbr": 'B',
+							"is_additional_component": 1,
+							"type": "Earning"
+						}
+					])
 	if setup or test_tax:
 		make_salary_component(data, test_tax)
 	data.append({
@@ -374,6 +434,12 @@
 
 	return data
 
+def get_tax_paid_in_period(employee):
+	tax_paid_amount = frappe.db.sql("""select sum(sd.amount) from `tabSalary Detail`
+		sd join `tabSalary Slip` ss where ss.name=sd.parent and ss.employee=%s
+		and ss.docstatus=1 and sd.salary_component='TDS'""", (employee))
+	return tax_paid_amount[0][0]
+
 def create_exemption_declaration(employee, payroll_period):
 	create_exemption_category()
 	declaration = frappe.get_doc({"doctype": "Employee Tax Exemption Declaration",
@@ -392,11 +458,17 @@
 									"payroll_period": payroll_period.name,
 									"submission_date": submission_date})
 	proof_submission.append("tax_exemption_proofs", {"exemption_sub_category": "_Test Sub Category",
-							"exemption_category": "_Test Category", "type_of_proof": "Test",
-							"amount": amount})
+				"exemption_category": "_Test Category", "type_of_proof": "Test", "amount": amount})
 	proof_submission.submit()
 	return submission_date
 
+def create_benefit_claim(employee, payroll_period, amount, component):
+	claim_date = add_months(payroll_period.start_date, random.randint(0, 11))
+	frappe.get_doc({"doctype": "Employee Benefit Claim", "employee": employee,
+		"claimed_amount": amount, "claim_date": claim_date, "earning_component":
+		component}).submit()
+	return claim_date
+
 def create_tax_slab(payroll_period):
 	data = [{
 				"from_amount": 250000,
@@ -417,7 +489,7 @@
 		payroll_period.append("taxable_salary_slabs", item)
 	payroll_period.save()
 
-def create_salary_slips_for_payroll_period(employee, salary_structure, payroll_period, deduct_random=False):
+def create_salary_slips_for_payroll_period(employee, salary_structure, payroll_period, deduct_random=True):
 	deducted_dates = []
 	i = 0
 	while i < 12:
@@ -440,3 +512,12 @@
 		doc.submit()
 		i += 1
 	return deducted_dates
+
+def create_additional_salary(employee, payroll_period, amount):
+	salary_date = add_months(payroll_period.start_date, random.randint(0, 11))
+	frappe.get_doc({"doctype": "Additional Salary", "employee": employee,
+					"company": erpnext.get_default_company(),
+					"salary_component": "Perfomance Bonus",
+					"from_date": salary_date, "to_date": salary_date,
+					"amount": amount, "type": "Earning"}).submit()
+	return salary_date