mirror of
https://github.com/frappe/erpnext.git
synced 2026-05-27 08:54:45 +00:00
test: HRA Exemption in Employee Tax Exemption Declaration
This commit is contained in:
committed by
Nabin Hait
parent
2b65c9616f
commit
5e96a46c87
@@ -4,13 +4,15 @@
|
|||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
import frappe
|
import frappe
|
||||||
|
from frappe.tests.utils import FrappeTestCase
|
||||||
|
from frappe.utils import add_months, getdate
|
||||||
|
|
||||||
import erpnext
|
import erpnext
|
||||||
from erpnext.hr.doctype.employee.test_employee import make_employee
|
from erpnext.hr.doctype.employee.test_employee import make_employee
|
||||||
from erpnext.hr.utils import DuplicateDeclarationError
|
from erpnext.hr.utils import DuplicateDeclarationError
|
||||||
|
|
||||||
|
|
||||||
class TestEmployeeTaxExemptionDeclaration(unittest.TestCase):
|
class TestEmployeeTaxExemptionDeclaration(FrappeTestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
make_employee("employee@taxexepmtion.com")
|
make_employee("employee@taxexepmtion.com")
|
||||||
make_employee("employee1@taxexepmtion.com")
|
make_employee("employee1@taxexepmtion.com")
|
||||||
@@ -112,6 +114,257 @@ class TestEmployeeTaxExemptionDeclaration(unittest.TestCase):
|
|||||||
|
|
||||||
self.assertEqual(declaration.total_exemption_amount, 100000)
|
self.assertEqual(declaration.total_exemption_amount, 100000)
|
||||||
|
|
||||||
|
def test_india_hra_exemption(self):
|
||||||
|
setup_hra_exemption_prerequisites("Monthly")
|
||||||
|
employee = frappe.get_value("Employee", {"user_id": "employee@taxexepmtion.com"}, "name")
|
||||||
|
|
||||||
|
declaration = frappe.get_doc(
|
||||||
|
{
|
||||||
|
"doctype": "Employee Tax Exemption Declaration",
|
||||||
|
"employee": employee,
|
||||||
|
"company": "Test Company",
|
||||||
|
"payroll_period": "_Test Payroll Period 1",
|
||||||
|
"currency": "INR",
|
||||||
|
"monthly_house_rent": 50000,
|
||||||
|
"rented_in_metro_city": 1,
|
||||||
|
"declarations": [
|
||||||
|
dict(
|
||||||
|
exemption_sub_category="_Test Sub Category",
|
||||||
|
exemption_category="_Test Category",
|
||||||
|
amount=80000,
|
||||||
|
),
|
||||||
|
dict(
|
||||||
|
exemption_sub_category="_Test1 Sub Category",
|
||||||
|
exemption_category="_Test Category",
|
||||||
|
amount=60000,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
}
|
||||||
|
).insert()
|
||||||
|
|
||||||
|
# Monthly HRA received = 3000
|
||||||
|
# should set HRA exemption as per actual annual HRA because that's the minimum
|
||||||
|
self.assertEqual(declaration.monthly_hra_exemption, 3000)
|
||||||
|
self.assertEqual(declaration.annual_hra_exemption, 36000)
|
||||||
|
# 100000 Standard Exemption + 36000 HRA exemption
|
||||||
|
self.assertEqual(declaration.total_exemption_amount, 136000)
|
||||||
|
|
||||||
|
def test_india_hra_exemption_with_daily_payroll_frequency(self):
|
||||||
|
setup_hra_exemption_prerequisites("Daily")
|
||||||
|
employee = frappe.get_value("Employee", {"user_id": "employee@taxexepmtion.com"}, "name")
|
||||||
|
|
||||||
|
declaration = frappe.get_doc(
|
||||||
|
{
|
||||||
|
"doctype": "Employee Tax Exemption Declaration",
|
||||||
|
"employee": employee,
|
||||||
|
"company": "Test Company",
|
||||||
|
"payroll_period": "_Test Payroll Period 1",
|
||||||
|
"currency": "INR",
|
||||||
|
"monthly_house_rent": 170000,
|
||||||
|
"rented_in_metro_city": 1,
|
||||||
|
"declarations": [
|
||||||
|
dict(
|
||||||
|
exemption_sub_category="_Test1 Sub Category",
|
||||||
|
exemption_category="_Test Category",
|
||||||
|
amount=60000,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
}
|
||||||
|
).insert()
|
||||||
|
|
||||||
|
# Daily HRA received = 3000
|
||||||
|
# should set HRA exemption as per (rent - 10% of Basic Salary), that's the minimum
|
||||||
|
self.assertEqual(declaration.monthly_hra_exemption, 17916.67)
|
||||||
|
self.assertEqual(declaration.annual_hra_exemption, 215000)
|
||||||
|
# 50000 Standard Exemption + 215000 HRA exemption
|
||||||
|
self.assertEqual(declaration.total_exemption_amount, 265000)
|
||||||
|
|
||||||
|
def test_india_hra_exemption_with_weekly_payroll_frequency(self):
|
||||||
|
setup_hra_exemption_prerequisites("Weekly")
|
||||||
|
employee = frappe.get_value("Employee", {"user_id": "employee@taxexepmtion.com"}, "name")
|
||||||
|
|
||||||
|
declaration = frappe.get_doc(
|
||||||
|
{
|
||||||
|
"doctype": "Employee Tax Exemption Declaration",
|
||||||
|
"employee": employee,
|
||||||
|
"company": "Test Company",
|
||||||
|
"payroll_period": "_Test Payroll Period 1",
|
||||||
|
"currency": "INR",
|
||||||
|
"monthly_house_rent": 170000,
|
||||||
|
"rented_in_metro_city": 1,
|
||||||
|
"declarations": [
|
||||||
|
dict(
|
||||||
|
exemption_sub_category="_Test1 Sub Category",
|
||||||
|
exemption_category="_Test Category",
|
||||||
|
amount=60000,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
}
|
||||||
|
).insert()
|
||||||
|
|
||||||
|
# Weekly HRA received = 3000
|
||||||
|
# should set HRA exemption as per actual annual HRA because that's the minimum
|
||||||
|
self.assertEqual(declaration.monthly_hra_exemption, 13000)
|
||||||
|
self.assertEqual(declaration.annual_hra_exemption, 156000)
|
||||||
|
# 50000 Standard Exemption + 156000 HRA exemption
|
||||||
|
self.assertEqual(declaration.total_exemption_amount, 206000)
|
||||||
|
|
||||||
|
def test_india_hra_exemption_with_fortnightly_payroll_frequency(self):
|
||||||
|
setup_hra_exemption_prerequisites("Fortnightly")
|
||||||
|
employee = frappe.get_value("Employee", {"user_id": "employee@taxexepmtion.com"}, "name")
|
||||||
|
|
||||||
|
declaration = frappe.get_doc(
|
||||||
|
{
|
||||||
|
"doctype": "Employee Tax Exemption Declaration",
|
||||||
|
"employee": employee,
|
||||||
|
"company": "Test Company",
|
||||||
|
"payroll_period": "_Test Payroll Period 1",
|
||||||
|
"currency": "INR",
|
||||||
|
"monthly_house_rent": 170000,
|
||||||
|
"rented_in_metro_city": 1,
|
||||||
|
"declarations": [
|
||||||
|
dict(
|
||||||
|
exemption_sub_category="_Test1 Sub Category",
|
||||||
|
exemption_category="_Test Category",
|
||||||
|
amount=60000,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
}
|
||||||
|
).insert()
|
||||||
|
|
||||||
|
# Fortnightly HRA received = 3000
|
||||||
|
# should set HRA exemption as per actual annual HRA because that's the minimum
|
||||||
|
self.assertEqual(declaration.monthly_hra_exemption, 6500)
|
||||||
|
self.assertEqual(declaration.annual_hra_exemption, 78000)
|
||||||
|
# 50000 Standard Exemption + 78000 HRA exemption
|
||||||
|
self.assertEqual(declaration.total_exemption_amount, 128000)
|
||||||
|
|
||||||
|
def test_india_hra_exemption_with_bimonthly_payroll_frequency(self):
|
||||||
|
setup_hra_exemption_prerequisites("Bimonthly")
|
||||||
|
employee = frappe.get_value("Employee", {"user_id": "employee@taxexepmtion.com"}, "name")
|
||||||
|
|
||||||
|
declaration = frappe.get_doc(
|
||||||
|
{
|
||||||
|
"doctype": "Employee Tax Exemption Declaration",
|
||||||
|
"employee": employee,
|
||||||
|
"company": "Test Company",
|
||||||
|
"payroll_period": "_Test Payroll Period 1",
|
||||||
|
"currency": "INR",
|
||||||
|
"monthly_house_rent": 50000,
|
||||||
|
"rented_in_metro_city": 1,
|
||||||
|
"declarations": [
|
||||||
|
dict(
|
||||||
|
exemption_sub_category="_Test Sub Category",
|
||||||
|
exemption_category="_Test Category",
|
||||||
|
amount=80000,
|
||||||
|
),
|
||||||
|
dict(
|
||||||
|
exemption_sub_category="_Test1 Sub Category",
|
||||||
|
exemption_category="_Test Category",
|
||||||
|
amount=60000,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
}
|
||||||
|
).insert()
|
||||||
|
|
||||||
|
# Bimonthly HRA received = 3000
|
||||||
|
# should set HRA exemption as per actual annual HRA because that's the minimum
|
||||||
|
self.assertEqual(declaration.monthly_hra_exemption, 1500)
|
||||||
|
self.assertEqual(declaration.annual_hra_exemption, 18000)
|
||||||
|
# 100000 Standard Exemption + 18000 HRA exemption
|
||||||
|
self.assertEqual(declaration.total_exemption_amount, 118000)
|
||||||
|
|
||||||
|
def test_india_hra_exemption_with_multiple_salary_structure_assignments(self):
|
||||||
|
from erpnext.payroll.doctype.salary_slip.test_salary_slip import create_tax_slab
|
||||||
|
from erpnext.payroll.doctype.salary_structure.test_salary_structure import (
|
||||||
|
create_salary_structure_assignment,
|
||||||
|
make_salary_structure,
|
||||||
|
)
|
||||||
|
|
||||||
|
payroll_period = create_payroll_period(name="_Test Payroll Period 1", company="_Test Company")
|
||||||
|
|
||||||
|
create_tax_slab(
|
||||||
|
payroll_period,
|
||||||
|
allow_tax_exemption=True,
|
||||||
|
currency="INR",
|
||||||
|
effective_date=getdate("2019-04-01"),
|
||||||
|
company="_Test Company",
|
||||||
|
)
|
||||||
|
|
||||||
|
frappe.db.set_value(
|
||||||
|
"Company", "_Test Company", {"basic_component": "Basic Salary", "hra_component": "HRA"}
|
||||||
|
)
|
||||||
|
|
||||||
|
employee = frappe.get_value("Employee", {"user_id": "employee@taxexepmtion.com"}, "name")
|
||||||
|
|
||||||
|
# salary structure with base 50000, HRA 3000
|
||||||
|
make_salary_structure(
|
||||||
|
"Monthly Structure for HRA Exemption 1",
|
||||||
|
"Monthly",
|
||||||
|
employee=employee,
|
||||||
|
company="_Test Company",
|
||||||
|
currency="INR",
|
||||||
|
payroll_period=payroll_period.name,
|
||||||
|
from_date=payroll_period.start_date,
|
||||||
|
)
|
||||||
|
|
||||||
|
# salary structure with base 70000, HRA = base * 0.2 = 14000
|
||||||
|
salary_structure = make_salary_structure(
|
||||||
|
"Monthly Structure for HRA Exemption 2",
|
||||||
|
"Monthly",
|
||||||
|
employee=employee,
|
||||||
|
company="_Test Company",
|
||||||
|
currency="INR",
|
||||||
|
payroll_period=payroll_period.name,
|
||||||
|
from_date=payroll_period.start_date,
|
||||||
|
dont_submit=True,
|
||||||
|
)
|
||||||
|
for component_row in salary_structure.earnings:
|
||||||
|
if component_row.salary_component == "HRA":
|
||||||
|
component_row.amount = 0
|
||||||
|
component_row.amount_based_on_formula = 1
|
||||||
|
component_row.formula = "base * 0.2"
|
||||||
|
break
|
||||||
|
|
||||||
|
salary_structure.submit()
|
||||||
|
|
||||||
|
create_salary_structure_assignment(
|
||||||
|
employee,
|
||||||
|
salary_structure.name,
|
||||||
|
from_date=add_months(payroll_period.start_date, 6),
|
||||||
|
company="_Test Company",
|
||||||
|
currency="INR",
|
||||||
|
payroll_period=payroll_period.name,
|
||||||
|
base=70000,
|
||||||
|
allow_duplicate=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
declaration = frappe.get_doc(
|
||||||
|
{
|
||||||
|
"doctype": "Employee Tax Exemption Declaration",
|
||||||
|
"employee": employee,
|
||||||
|
"company": "Test Company",
|
||||||
|
"payroll_period": "_Test Payroll Period 1",
|
||||||
|
"currency": "INR",
|
||||||
|
"monthly_house_rent": 50000,
|
||||||
|
"rented_in_metro_city": 1,
|
||||||
|
"declarations": [
|
||||||
|
dict(
|
||||||
|
exemption_sub_category="_Test1 Sub Category",
|
||||||
|
exemption_category="_Test Category",
|
||||||
|
amount=60000,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
}
|
||||||
|
).insert()
|
||||||
|
|
||||||
|
# Monthly HRA received = 50000 * 6 months + 70000 * 6 months
|
||||||
|
# should set HRA exemption as per actual annual HRA because that's the minimum
|
||||||
|
self.assertEqual(declaration.monthly_hra_exemption, 8500)
|
||||||
|
self.assertEqual(declaration.annual_hra_exemption, 102000)
|
||||||
|
# 50000 Standard Exemption + 102000 HRA exemption
|
||||||
|
self.assertEqual(declaration.total_exemption_amount, 152000)
|
||||||
|
|
||||||
|
|
||||||
def create_payroll_period(**args):
|
def create_payroll_period(**args):
|
||||||
args = frappe._dict(args)
|
args = frappe._dict(args)
|
||||||
@@ -163,3 +416,31 @@ def create_exemption_category():
|
|||||||
"is_active": 1,
|
"is_active": 1,
|
||||||
}
|
}
|
||||||
).insert()
|
).insert()
|
||||||
|
|
||||||
|
|
||||||
|
def setup_hra_exemption_prerequisites(frequency):
|
||||||
|
from erpnext.payroll.doctype.salary_slip.test_salary_slip import create_tax_slab
|
||||||
|
from erpnext.payroll.doctype.salary_structure.test_salary_structure import make_salary_structure
|
||||||
|
|
||||||
|
payroll_period = create_payroll_period(name="_Test Payroll Period 1", company="_Test Company")
|
||||||
|
|
||||||
|
create_tax_slab(
|
||||||
|
payroll_period,
|
||||||
|
allow_tax_exemption=True,
|
||||||
|
currency="INR",
|
||||||
|
effective_date=getdate("2019-04-01"),
|
||||||
|
company="_Test Company",
|
||||||
|
)
|
||||||
|
|
||||||
|
make_salary_structure(
|
||||||
|
f"{frequency} Structure for HRA Exemption",
|
||||||
|
frequency,
|
||||||
|
employee=frappe.get_value("Employee", {"user_id": "employee@taxexepmtion.com"}, "name"),
|
||||||
|
company="_Test Company",
|
||||||
|
currency="INR",
|
||||||
|
payroll_period=payroll_period,
|
||||||
|
)
|
||||||
|
|
||||||
|
frappe.db.set_value(
|
||||||
|
"Company", "_Test Company", {"basic_component": "Basic Salary", "hra_component": "HRA"}
|
||||||
|
)
|
||||||
|
|||||||
@@ -230,9 +230,12 @@ def create_salary_structure_assignment(
|
|||||||
company=None,
|
company=None,
|
||||||
currency=erpnext.get_default_currency(),
|
currency=erpnext.get_default_currency(),
|
||||||
payroll_period=None,
|
payroll_period=None,
|
||||||
|
base=None,
|
||||||
|
allow_duplicate=False,
|
||||||
):
|
):
|
||||||
|
if not allow_duplicate and frappe.db.exists(
|
||||||
if frappe.db.exists("Salary Structure Assignment", {"employee": employee}):
|
"Salary Structure Assignment", {"employee": employee}
|
||||||
|
):
|
||||||
frappe.db.sql("""delete from `tabSalary Structure Assignment` where employee=%s""", (employee))
|
frappe.db.sql("""delete from `tabSalary Structure Assignment` where employee=%s""", (employee))
|
||||||
|
|
||||||
if not payroll_period:
|
if not payroll_period:
|
||||||
@@ -245,7 +248,7 @@ def create_salary_structure_assignment(
|
|||||||
|
|
||||||
salary_structure_assignment = frappe.new_doc("Salary Structure Assignment")
|
salary_structure_assignment = frappe.new_doc("Salary Structure Assignment")
|
||||||
salary_structure_assignment.employee = employee
|
salary_structure_assignment.employee = employee
|
||||||
salary_structure_assignment.base = 50000
|
salary_structure_assignment.base = base or 50000
|
||||||
salary_structure_assignment.variable = 5000
|
salary_structure_assignment.variable = 5000
|
||||||
|
|
||||||
if not from_date:
|
if not from_date:
|
||||||
|
|||||||
Reference in New Issue
Block a user