def make_salary_structure_for_timesheet(employee, company=None): salary_structure_name = "Timesheet Salary Structure Test" frequency = "Monthly" if not frappe.db.exists("Salary Component", "Timesheet Component"): frappe.get_doc({ "doctype": "Salary Component", "salary_component": "Timesheet Component" }).insert() salary_structure = make_salary_structure(salary_structure_name, frequency, company=company, dont_submit=True) salary_structure.salary_component = "Timesheet Component" salary_structure.salary_slip_based_on_timesheet = 1 salary_structure.hour_rate = 50.0 salary_structure.save() salary_structure.submit() if not frappe.db.get_value("Salary Structure Assignment", { "employee": employee, "docstatus": 1 }): frappe.db.set_value("Employee", employee, "date_of_joining", add_months(nowdate(), -5)) create_salary_structure_assignment(employee, salary_structure.name) return salary_structure
def test_multi_currency_payroll_entry(self): # pylint: disable=no-self-use company = erpnext.get_default_company() employee = make_employee("*****@*****.**", company=company) for data in frappe.get_all('Salary Component', fields=["name"]): if not frappe.db.get_value('Salary Component Account', { 'parent': data.name, 'company': company }, 'name'): get_salary_component_account(data.name) company_doc = frappe.get_doc('Company', company) salary_structure = make_salary_structure( "_Test Multi Currency Salary Structure", "Monthly", company=company, currency='USD') create_salary_structure_assignment(employee, salary_structure.name, company=company, currency='USD') frappe.db.sql( """delete from `tabSalary Slip` where employee=%s""", (frappe.db.get_value( "Employee", {"user_id": "*****@*****.**"}))) salary_slip = get_salary_slip( "*****@*****.**", "Monthly", "_Test Multi Currency Salary Structure") dates = get_start_end_dates('Monthly', nowdate()) payroll_entry = make_payroll_entry( start_date=dates.start_date, end_date=dates.end_date, payable_account=company_doc.default_payroll_payable_account, currency='USD', exchange_rate=70) payroll_entry.make_payment_entry() salary_slip.load_from_db() payroll_je = salary_slip.journal_entry if payroll_je: payroll_je_doc = frappe.get_doc('Journal Entry', payroll_je) self.assertEqual(salary_slip.base_gross_pay, payroll_je_doc.total_debit) self.assertEqual(salary_slip.base_gross_pay, payroll_je_doc.total_credit) payment_entry = frappe.db.sql(''' Select ifnull(sum(je.total_debit),0) as total_debit, ifnull(sum(je.total_credit),0) as total_credit from `tabJournal Entry` je, `tabJournal Entry Account` jea Where je.name = jea.parent And jea.reference_name = %s ''', (payroll_entry.name), as_dict=1) self.assertEqual(salary_slip.base_net_pay, payment_entry[0].total_debit) self.assertEqual(salary_slip.base_net_pay, payment_entry[0].total_credit)
def make_salary_structure_for_timesheet(employee): salary_structure_name = "Timesheet Salary Structure Test" frequency = "Monthly" salary_structure = make_salary_structure( salary_structure_name, frequency, dont_submit=True) salary_structure.salary_component = "Timesheet Component" salary_structure.salary_slip_based_on_timesheet = 1 salary_structure.hour_rate = 50.0 salary_structure.save() salary_structure.submit() if not frappe.db.get_value("Salary Structure Assignment", {'employee': employee, 'docstatus': 1}): frappe.db.set_value('Employee', employee, 'date_of_joining', add_months(nowdate(), -5)) create_salary_structure_assignment(employee, salary_structure.name) return salary_structure
def test_tax_for_payroll_period(self): data = {} # test the impact of tax exemption declaration, tax exemption proof submission # and deduct check boxes in annual tax calculation # as per assigned salary structure 40500 in monthly salary so 236000*5/100/12 frappe.db.sql("""delete from `tabPayroll Period`""") frappe.db.sql("""delete from `tabSalary Component`""") frappe.db.sql("""delete from `tabAdditional Salary`""") payroll_period = create_payroll_period() create_tax_slab(payroll_period, allow_tax_exemption=True) employee = make_employee("*****@*****.**") 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)) from erpnext.payroll.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) # 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) annual_tax = 113589.0 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) tax_paid = get_tax_paid_in_period(employee) # No proof, benefit claim sumitted, total tax paid, should not change try: self.assertEqual(tax_paid, annual_tax) except AssertionError: print("\nSalary Slip - Tax calculation failed on following case\n", data, "\n") raise # Submit proof for total 120000 data["proof"] = create_proof_submission(employee, payroll_period, 120000) # 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) tax_paid = get_tax_paid_in_period(employee) # total taxable income 416000, 166000 @ 5% ie. 8300 try: self.assertEqual(tax_paid, 82389.0) except AssertionError: 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, 150000) 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, annual_tax) 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)) # undelete fixture data frappe.db.rollback()
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, ) # set country current_country = frappe.flags.country frappe.flags.country = "India" employee = make_employee("*****@*****.**", company="_Test Company") payroll_period = create_payroll_period(name="_Test Payroll Period", 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"} ) # 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": payroll_period.name, "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) # reset frappe.flags.country = current_country