def setUp(self): create_loan_accounts() create_loan_type("Home Loan", 500000, 9.2, 0, 1, 0, 'Cash', 'Payment Account - _TC', 'Loan Account - _TC', 'Interest Income Account - _TC', 'Penalty Income Account - _TC', 'Repay Over Number of Periods', 18) self.applicant = make_employee("*****@*****.**", "_Test Company") make_salary_structure("Test Salary Structure Loan", "Monthly", employee=self.applicant, currency='INR') self.create_loan_application()
def setup_hra_exemption_prerequisites(frequency, employee=None): 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", company="_Test Company") if not employee: employee = frappe.get_value("Employee", {"user_id": "*****@*****.**"}, "name") 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=employee, company="_Test Company", currency="INR", payroll_period=payroll_period, ) frappe.db.set_value( "Company", "_Test Company", {"basic_component": "Basic Salary", "hra_component": "HRA"} )
def setUp(self): create_loan_accounts() create_loan_type("Personal Loan", 500000, 8.4, is_term_loan=1, mode_of_payment='Cash', payment_account='Payment Account - _TC', loan_account='Loan Account - _TC', interest_income_account='Interest Income Account - _TC', penalty_income_account='Penalty Income Account - _TC') create_loan_type("Stock Loan", 2000000, 13.5, 25, 1, 5, 'Cash', 'Payment Account - _TC', 'Loan Account - _TC', 'Interest Income Account - _TC', 'Penalty Income Account - _TC') create_loan_type("Demand Loan", 2000000, 13.5, 25, 0, 5, 'Cash', 'Payment Account - _TC', 'Loan Account - _TC', 'Interest Income Account - _TC', 'Penalty Income Account - _TC') create_loan_security_type() create_loan_security() create_loan_security_price("Test Security 1", 500, "Nos", get_datetime() , get_datetime(add_to_date(nowdate(), hours=24))) create_loan_security_price("Test Security 2", 250, "Nos", get_datetime() , get_datetime(add_to_date(nowdate(), hours=24))) self.applicant1 = make_employee("*****@*****.**") make_salary_structure("Test Salary Structure Loan", "Monthly", employee=self.applicant1, currency='INR', company="_Test Company") if not frappe.db.exists("Customer", "_Test Loan Customer"): frappe.get_doc(get_customer_dict('_Test Loan Customer')).insert(ignore_permissions=True) self.applicant2 = frappe.db.get_value("Customer", {'name': '_Test Loan Customer'}, 'name') create_loan(self.applicant1, "Personal Loan", 280000, "Repay Over Number of Periods", 20)
def test_payroll_entry(self): # pylint: disable=no-self-use company = erpnext.get_default_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) employee = frappe.db.get_value("Employee", {"company": company}) company_doc = frappe.get_doc("Company", company) make_salary_structure( "_Test Salary Structure", "Monthly", employee, company=company, currency=company_doc.default_currency, ) dates = get_start_end_dates("Monthly", nowdate()) if not frappe.db.get_value("Salary Slip", { "start_date": dates.start_date, "end_date": dates.end_date }): make_payroll_entry( start_date=dates.start_date, end_date=dates.end_date, payable_account=company_doc.default_payroll_payable_account, currency=company_doc.default_currency, )
def test_loan(self): branch = "Test Employee Branch" applicant = make_employee( "*****@*****.**", company="_Test Company") company = "_Test Company" holiday_list = make_holiday("test holiday for loan") company_doc = frappe.get_doc('Company', company) if not company_doc.default_payroll_payable_account: company_doc.default_payroll_payable_account = frappe.db.get_value('Account', {'company': company, 'root_type': 'Liability', 'account_type': ''}, 'name') company_doc.save() if not frappe.db.exists('Branch', branch): frappe.get_doc({ 'doctype': 'Branch', 'branch': branch }).insert() employee_doc = frappe.get_doc('Employee', applicant) employee_doc.branch = branch employee_doc.holiday_list = holiday_list employee_doc.save() salary_structure = "Test Salary Structure for Loan" make_salary_structure(salary_structure, "Monthly", employee=employee_doc.name, company="_Test Company", currency=company_doc.default_currency) loan = create_loan(applicant, "Car Loan", 280000, "Repay Over Number of Periods", 20, posting_date=add_months(nowdate(), -1)) loan.repay_from_salary = 1 loan.submit() make_loan_disbursement_entry( loan.name, loan.loan_amount, disbursement_date=add_months(nowdate(), -1)) process_loan_interest_accrual_for_term_loans(posting_date=nowdate()) dates = get_start_end_dates('Monthly', nowdate()) make_payroll_entry(company="_Test Company", start_date=dates.start_date, payable_account=company_doc.default_payroll_payable_account, currency=company_doc.default_currency, end_date=dates.end_date, branch=branch, cost_center="Main - _TC", payment_account="Cash - _TC") name = frappe.db.get_value('Salary Slip', {'posting_date': nowdate(), 'employee': applicant}, 'name') salary_slip = frappe.get_doc('Salary Slip', name) for row in salary_slip.loans: if row.loan == loan.name: interest_amount = (280000 * 8.4)/(12*100) principal_amount = loan.monthly_repayment_amount - interest_amount self.assertEqual(row.interest_amount, interest_amount) self.assertEqual(row.principal_amount, principal_amount) self.assertEqual(row.total_payment, interest_amount + principal_amount) if salary_slip.docstatus == 0: frappe.delete_doc('Salary Slip', name)
def test_loan_repayment_salary_slip(self): from erpnext.loan_management.doctype.loan.test_loan import create_loan_type, create_loan, make_loan_disbursement_entry, create_loan_accounts from erpnext.loan_management.doctype.process_loan_interest_accrual.process_loan_interest_accrual import process_loan_interest_accrual_for_term_loans from erpnext.payroll.doctype.salary_structure.test_salary_structure import make_salary_structure applicant = make_employee("*****@*****.**", company="_Test Company") create_loan_accounts() create_loan_type( "Car Loan", 500000, 8.4, is_term_loan=1, mode_of_payment='Cash', payment_account='Payment Account - _TC', loan_account='Loan Account - _TC', interest_income_account='Interest Income Account - _TC', penalty_income_account='Penalty Income Account - _TC') payroll_period = create_payroll_period(name="_Test Payroll Period 1", company="_Test Company") make_salary_structure("Test Loan Repayment Salary Structure", "Monthly", employee=applicant, currency='INR', payroll_period=payroll_period) frappe.db.sql("delete from tabLoan") loan = create_loan(applicant, "Car Loan", 11000, "Repay Over Number of Periods", 20, posting_date=add_months(nowdate(), -1)) loan.repay_from_salary = 1 loan.submit() make_loan_disbursement_entry(loan.name, loan.loan_amount, disbursement_date=add_months( nowdate(), -1)) process_loan_interest_accrual_for_term_loans(posting_date=nowdate()) ss = make_employee_salary_slip( "*****@*****.**", "Monthly", "Test Loan Repayment Salary Structure") ss.submit() self.assertEqual(ss.total_loan_repayment, 592) self.assertEqual( ss.net_pay, (flt(ss.gross_pay) - (flt(ss.total_deduction) + flt(ss.total_loan_repayment))))
def test_payroll_entry_with_employee_cost_center(self): # pylint: disable=no-self-use for data in frappe.get_all('Salary Component', fields = ["name"]): if not frappe.db.get_value('Salary Component Account', {'parent': data.name, 'company': "_Test Company"}, 'name'): get_salary_component_account(data.name) if not frappe.db.exists('Department', "cc - _TC"): frappe.get_doc({ 'doctype': 'Department', 'department_name': "cc", "company": "_Test Company" }).insert() frappe.db.sql("""delete from `tabEmployee` where employee_name='*****@*****.**' """) frappe.db.sql("""delete from `tabEmployee` where employee_name='*****@*****.**' """) frappe.db.sql("""delete from `tabSalary Structure` where name='_Test Salary Structure 1' """) frappe.db.sql("""delete from `tabSalary Structure` where name='_Test Salary Structure 2' """) employee1 = make_employee("*****@*****.**", payroll_cost_center="_Test Cost Center - _TC", department="cc - _TC", company="_Test Company") employee2 = make_employee("*****@*****.**", payroll_cost_center="_Test Cost Center 2 - _TC", department="cc - _TC", company="_Test Company") if not frappe.db.exists("Account", "_Test Payroll Payable - _TC"): create_account(account_name="_Test Payroll Payable", company="_Test Company", parent_account="Current Liabilities - _TC") if not frappe.db.get_value("Company", "_Test Company", "default_payroll_payable_account") or \ frappe.db.get_value("Company", "_Test Company", "default_payroll_payable_account") != "_Test Payroll Payable - _TC": frappe.db.set_value("Company", "_Test Company", "default_payroll_payable_account", "_Test Payroll Payable - _TC") currency=frappe.db.get_value("Company", "_Test Company", "default_currency") make_salary_structure("_Test Salary Structure 1", "Monthly", employee1, company="_Test Company", currency=currency, test_tax=False) make_salary_structure("_Test Salary Structure 2", "Monthly", employee2, company="_Test Company", currency=currency, test_tax=False) dates = get_start_end_dates('Monthly', nowdate()) if not frappe.db.get_value("Salary Slip", {"start_date": dates.start_date, "end_date": dates.end_date}): pe = make_payroll_entry(start_date=dates.start_date, end_date=dates.end_date, payable_account="_Test Payroll Payable - _TC", currency=frappe.db.get_value("Company", "_Test Company", "default_currency"), department="cc - _TC", company="_Test Company", payment_account="Cash - _TC", cost_center="Main - _TC") je = frappe.db.get_value("Salary Slip", {"payroll_entry": pe.name}, "journal_entry") je_entries = frappe.db.sql(""" select account, cost_center, debit, credit from `tabJournal Entry Account` where parent=%s order by account, cost_center """, je) expected_je = ( ('_Test Payroll Payable - _TC', 'Main - _TC', 0.0, 155600.0), ('Salary - _TC', '_Test Cost Center - _TC', 78000.0, 0.0), ('Salary - _TC', '_Test Cost Center 2 - _TC', 78000.0, 0.0), ('Salary Deductions - _TC', '_Test Cost Center - _TC', 0.0, 200.0), ('Salary Deductions - _TC', '_Test Cost Center 2 - _TC', 0.0, 200.0) ) self.assertEqual(je_entries, expected_je)
def create_records(self): self.employee = make_employee( "*****@*****.**", company="_Test Company", date_of_joining=getdate("01-10-2021"), ) self.payroll_period = create_payroll_period( name="_Test Payroll Period 1", company="_Test Company") self.income_tax_slab = create_tax_slab( self.payroll_period, allow_tax_exemption=True, effective_date=getdate("2019-04-01"), company="_Test Company", ) salary_structure = make_salary_structure( "Monthly Salary Structure Test Income Tax Computation", "Monthly", employee=self.employee, company="_Test Company", currency="INR", payroll_period=self.payroll_period, test_tax=True, ) create_exemption_declaration(self.employee, self.payroll_period.name) create_salary_slips_for_payroll_period(self.employee, salary_structure.name, self.payroll_period, deduct_random=False, num=3)
def setUp(self): frappe.db.sql("""delete from `tabLeave Period`""") frappe.db.sql("""delete from `tabLeave Policy Assignment`""") frappe.db.sql("""delete from `tabLeave Allocation`""") frappe.db.sql("""delete from `tabLeave Ledger Entry`""") frappe.db.sql("""delete from `tabAdditional Salary`""") # create the leave policy leave_policy = create_leave_policy( leave_type="_Test Leave Type Encashment", annual_allocation=10) leave_policy.submit() # create employee, salary structure and assignment self.employee = make_employee("*****@*****.**") self.leave_period = create_leave_period(add_months(today(), -3), add_months(today(), 3)) data = { "assignment_based_on": "Leave Period", "leave_policy": leave_policy.name, "leave_period": self.leave_period.name, } leave_policy_assignments = create_assignment_for_multiple_employees( [self.employee], frappe._dict(data)) salary_structure = make_salary_structure( "Salary Structure for Encashment", "Monthly", self.employee, other_details={"leave_encashment_amount_per_day": 50}, )
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_year_to_date_computation(self): from erpnext.payroll.doctype.salary_structure.test_salary_structure import make_salary_structure applicant = make_employee("*****@*****.**", company="_Test Company") 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") salary_structure = make_salary_structure("Monthly Salary Structure Test for Salary Slip YTD", "Monthly", employee=applicant, company="_Test Company", currency="INR", payroll_period=payroll_period) # clear salary slip for this employee frappe.db.sql("DELETE FROM `tabSalary Slip` where employee_name = '*****@*****.**'") create_salary_slips_for_payroll_period(applicant, salary_structure.name, payroll_period, deduct_random=False) salary_slips = frappe.get_all('Salary Slip', fields=['year_to_date', 'net_pay'], filters={'employee_name': '*****@*****.**'}, order_by = 'posting_date') year_to_date = 0 for slip in salary_slips: year_to_date += flt(slip.net_pay) self.assertEqual(slip.year_to_date, year_to_date)
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 setUp(self): frappe.db.sql('''delete from `tabLeave Period`''') frappe.db.sql('''delete from `tabLeave Allocation`''') frappe.db.sql('''delete from `tabLeave Ledger Entry`''') frappe.db.sql('''delete from `tabAdditional Salary`''') # create the leave policy leave_policy = create_leave_policy( leave_type="_Test Leave Type Encashment", annual_allocation=10) leave_policy.submit() # create employee, salary structure and assignment self.employee = make_employee("*****@*****.**") frappe.db.set_value("Employee", self.employee, "leave_policy", leave_policy.name) salary_structure = make_salary_structure( "Salary Structure for Encashment", "Monthly", self.employee, other_details={"leave_encashment_amount_per_day": 50}) # create the leave period and assign the leaves self.leave_period = create_leave_period(add_months(today(), -3), add_months(today(), 3)) self.leave_period.grant_leave_allocation(employee=self.employee)
def test_employee_status_inactive(self): from erpnext.payroll.doctype.salary_slip.test_salary_slip import make_holiday_list from erpnext.payroll.doctype.salary_structure.salary_structure import make_salary_slip from erpnext.payroll.doctype.salary_structure.test_salary_structure import make_salary_structure employee = make_employee("*****@*****.**") employee_doc = frappe.get_doc("Employee", employee) employee_doc.status = "Inactive" employee_doc.save() employee_doc.reload() make_holiday_list() frappe.db.set_value("Company", employee_doc.company, "default_holiday_list", "Salary Slip Test Holiday List") frappe.db.sql( """delete from `tabSalary Structure` where name='Test Inactive Employee Salary Slip'""" ) salary_structure = make_salary_structure( "Test Inactive Employee Salary Slip", "Monthly", employee=employee_doc.name, company=employee_doc.company, ) salary_slip = make_salary_slip(salary_structure.name, employee=employee_doc.name) self.assertRaises(InactiveEmployeeStatusError, salary_slip.save)
def make_employee_salary_slip(user, payroll_frequency, salary_structure=None): from erpnext.payroll.doctype.salary_structure.test_salary_structure import make_salary_structure if not salary_structure: salary_structure = payroll_frequency + " Salary Structure Test for Salary Slip" employee = frappe.db.get_value("Employee", {"user_id": user}) if not frappe.db.exists('Salary Structure', salary_structure): salary_structure_doc = make_salary_structure(salary_structure, payroll_frequency, employee) else: salary_structure_doc = frappe.get_doc('Salary Structure', salary_structure) salary_slip_name = frappe.db.get_value( "Salary Slip", {"employee": frappe.db.get_value("Employee", {"user_id": user})}) if not salary_slip_name: salary_slip = make_salary_slip(salary_structure_doc.name, employee=employee) salary_slip.employee_name = frappe.get_value( "Employee", {"name": frappe.db.get_value("Employee", {"user_id": user})}, "employee_name") salary_slip.payroll_frequency = payroll_frequency salary_slip.posting_date = nowdate() salary_slip.insert() else: salary_slip = frappe.get_doc('Salary Slip', salary_slip_name) return salary_slip
def test_component_wise_year_to_date_computation(self): from erpnext.payroll.doctype.salary_structure.test_salary_structure import make_salary_structure applicant = make_employee("*****@*****.**", company="_Test Company") 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") salary_structure = make_salary_structure("Monthly Salary Structure Test for Salary Slip YTD", "Monthly", employee=applicant, company="_Test Company", currency="INR", payroll_period=payroll_period) # clear salary slip for this employee frappe.db.sql("DELETE FROM `tabSalary Slip` where employee_name = '*****@*****.**'") create_salary_slips_for_payroll_period(applicant, salary_structure.name, payroll_period, deduct_random=False, num=3) salary_slips = frappe.get_all("Salary Slip", fields=["name"], filters={"employee_name": "*****@*****.**"}, order_by = "posting_date") year_to_date = dict() for slip in salary_slips: doc = frappe.get_doc("Salary Slip", slip.name) for entry in doc.get("earnings"): if not year_to_date.get(entry.salary_component): year_to_date[entry.salary_component] = 0 year_to_date[entry.salary_component] += entry.amount self.assertEqual(year_to_date[entry.salary_component], entry.year_to_date)
def test_repay_unclaimed_amount_from_salary(self): employee_name = make_employee("*****@*****.**") advance = make_employee_advance( employee_name, {"repay_unclaimed_amount_from_salary": 1}) pe = make_payment_entry(advance) pe.submit() args = {"type": "Deduction"} create_salary_component("Advance Salary - Deduction", **args) make_salary_structure("Test Additional Salary for Advance Return", "Monthly", employee=employee_name) # additional salary for 700 first advance.reload() additional_salary = create_return_through_additional_salary(advance) additional_salary.salary_component = "Advance Salary - Deduction" additional_salary.payroll_date = nowdate() additional_salary.amount = 700 additional_salary.insert() additional_salary.submit() advance.reload() self.assertEqual(advance.return_amount, 700) # additional salary for remaining 300 additional_salary = create_return_through_additional_salary(advance) additional_salary.salary_component = "Advance Salary - Deduction" additional_salary.payroll_date = nowdate() additional_salary.amount = 300 additional_salary.insert() additional_salary.submit() advance.reload() self.assertEqual(advance.return_amount, 1000) self.assertEqual(advance.status, "Returned") # update advance return amount on additional salary cancellation additional_salary.cancel() advance.reload() self.assertEqual(advance.return_amount, 700) self.assertEqual(advance.status, "Paid")
def test_multi_currency_salary_slip(self): from erpnext.payroll.doctype.salary_structure.test_salary_structure import make_salary_structure applicant = make_employee("*****@*****.**", company="_Test Company") frappe.db.sql("""delete from `tabSalary Structure` where name='Test Multi Currency Salary Slip'""") salary_structure = make_salary_structure("Test Multi Currency Salary Slip", "Monthly", employee=applicant, company="_Test Company", currency='USD') salary_slip = make_salary_slip(salary_structure.name, employee = applicant) salary_slip.exchange_rate = 70 salary_slip.calculate_net_pay() self.assertEqual(salary_slip.gross_pay, 78000) self.assertEqual(salary_slip.base_gross_pay, 78000*70)
def test_payroll_entry(self): # pylint: disable=no-self-use company = erpnext.get_default_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) employee = frappe.db.get_value("Employee", {'company': company}) make_salary_structure("_Test Salary Structure", "Monthly", employee, company=company) dates = get_start_end_dates('Monthly', nowdate()) if not frappe.db.get_value("Salary Slip", { "start_date": dates.start_date, "end_date": dates.end_date }): make_payroll_entry(start_date=dates.start_date, end_date=dates.end_date)
def setUp(self): create_loan_accounts() create_loan_type( "Home Loan", 500000, 9.2, 0, 1, 0, "Cash", "Disbursement Account - _TC", "Payment Account - _TC", "Loan Account - _TC", "Interest Income Account - _TC", "Penalty Income Account - _TC", "Repay Over Number of Periods", 18, ) self.applicant = make_employee("*****@*****.**", "_Test Company") make_salary_structure("Test Salary Structure Loan", "Monthly", employee=self.applicant, currency="INR") self.create_loan_application()
def test_recurring_additional_salary(self): amount = 0 salary_component = None emp_id = make_employee("*****@*****.**") frappe.db.set_value("Employee", emp_id, "relieving_date", add_days(nowdate(), 1800)) salary_structure = make_salary_structure("Test Salary Structure Additional Salary", "Monthly", employee=emp_id) add_sal = get_additional_salary(emp_id) ss = make_employee_salary_slip("*****@*****.**", "Monthly", salary_structure=salary_structure.name) 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 test_non_recurring_additional_salary(self): amount = 0 salary_component = None date = nowdate() emp_id = make_employee("*****@*****.**") frappe.db.set_value("Employee", emp_id, "relieving_date", add_days(date, 1800)) salary_structure = make_salary_structure( "Test Salary Structure Additional Salary", "Monthly", employee=emp_id) add_sal = get_additional_salary(emp_id, recurring=False, payroll_date=date) ss = make_employee_salary_slip("*****@*****.**", "Monthly", salary_structure=salary_structure.name) amount, salary_component = None, None for earning in ss.earnings: if earning.salary_component == "Recurring Salary Component": amount = earning.amount salary_component = earning.salary_component break self.assertEqual(amount, add_sal.amount) self.assertEqual(salary_component, add_sal.salary_component) # should not show up in next months ss.posting_date = add_months(date, 1) ss.start_date = ss.end_date = None ss.earnings = [] ss.deductions = [] ss.save() amount, salary_component = None, None for earning in ss.earnings: if earning.salary_component == "Recurring Salary Component": amount = earning.amount salary_component = earning.salary_component break self.assertIsNone(amount) self.assertIsNone(salary_component)
def setUp(self): frappe.db.delete("Leave Period") frappe.db.delete("Leave Policy Assignment") frappe.db.delete("Leave Allocation") frappe.db.delete("Leave Ledger Entry") frappe.db.delete("Additional Salary") frappe.db.delete("Leave Encashment") if not frappe.db.exists("Leave Type", "_Test Leave Type Encashment"): frappe.get_doc(test_records[2]).insert() date = getdate() year_start = getdate(get_year_start(date)) year_end = getdate(get_year_ending(date)) make_holiday_list("_Test Leave Encashment", year_start, year_end) # create the leave policy leave_policy = create_leave_policy( leave_type="_Test Leave Type Encashment", annual_allocation=10 ) leave_policy.submit() # create employee, salary structure and assignment self.employee = make_employee("*****@*****.**", company="_Test Company") self.leave_period = create_leave_period(year_start, year_end, "_Test Company") data = { "assignment_based_on": "Leave Period", "leave_policy": leave_policy.name, "leave_period": self.leave_period.name, } leave_policy_assignments = create_assignment_for_multiple_employees( [self.employee], frappe._dict(data) ) salary_structure = make_salary_structure( "Salary Structure for Encashment", "Monthly", self.employee, other_details={"leave_encashment_amount_per_day": 50}, )
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_payroll_entry_with_employee_cost_center(self): # pylint: disable=no-self-use for data in frappe.get_all("Salary Component", fields=["name"]): if not frappe.db.get_value("Salary Component Account", { "parent": data.name, "company": "_Test Company" }, "name"): get_salary_component_account(data.name) if not frappe.db.exists("Department", "cc - _TC"): frappe.get_doc({ "doctype": "Department", "department_name": "cc", "company": "_Test Company" }).insert() frappe.db.sql( """delete from `tabEmployee` where employee_name='*****@*****.**' """ ) frappe.db.sql( """delete from `tabEmployee` where employee_name='*****@*****.**' """ ) frappe.db.sql( """delete from `tabSalary Structure` where name='_Test Salary Structure 1' """ ) frappe.db.sql( """delete from `tabSalary Structure` where name='_Test Salary Structure 2' """ ) employee1 = make_employee( "*****@*****.**", payroll_cost_center="_Test Cost Center - _TC", department="cc - _TC", company="_Test Company", ) employee2 = make_employee("*****@*****.**", department="cc - _TC", company="_Test Company") if not frappe.db.exists("Account", "_Test Payroll Payable - _TC"): create_account( account_name="_Test Payroll Payable", company="_Test Company", parent_account="Current Liabilities - _TC", account_type="Payable", ) if (not frappe.db.get_value("Company", "_Test Company", "default_payroll_payable_account") or frappe.db.get_value("Company", "_Test Company", "default_payroll_payable_account") != "_Test Payroll Payable - _TC"): frappe.db.set_value("Company", "_Test Company", "default_payroll_payable_account", "_Test Payroll Payable - _TC") currency = frappe.db.get_value("Company", "_Test Company", "default_currency") make_salary_structure( "_Test Salary Structure 1", "Monthly", employee1, company="_Test Company", currency=currency, test_tax=False, ) ss = make_salary_structure( "_Test Salary Structure 2", "Monthly", employee2, company="_Test Company", currency=currency, test_tax=False, ) # update cost centers in salary structure assignment for employee2 ssa = frappe.db.get_value( "Salary Structure Assignment", { "employee": employee2, "salary_structure": ss.name, "docstatus": 1 }, "name", ) ssa_doc = frappe.get_doc("Salary Structure Assignment", ssa) ssa_doc.payroll_cost_centers = [] ssa_doc.append("payroll_cost_centers", { "cost_center": "_Test Cost Center - _TC", "percentage": 60 }) ssa_doc.append("payroll_cost_centers", { "cost_center": "_Test Cost Center 2 - _TC", "percentage": 40 }) ssa_doc.save() dates = get_start_end_dates("Monthly", nowdate()) if not frappe.db.get_value("Salary Slip", { "start_date": dates.start_date, "end_date": dates.end_date }): pe = make_payroll_entry( start_date=dates.start_date, end_date=dates.end_date, payable_account="_Test Payroll Payable - _TC", currency=frappe.db.get_value("Company", "_Test Company", "default_currency"), department="cc - _TC", company="_Test Company", payment_account="Cash - _TC", cost_center="Main - _TC", ) je = frappe.db.get_value("Salary Slip", {"payroll_entry": pe.name}, "journal_entry") je_entries = frappe.db.sql( """ select account, cost_center, debit, credit from `tabJournal Entry Account` where parent=%s order by account, cost_center """, je, ) expected_je = ( ("_Test Payroll Payable - _TC", "Main - _TC", 0.0, 155600.0), ("Salary - _TC", "_Test Cost Center - _TC", 124800.0, 0.0), ("Salary - _TC", "_Test Cost Center 2 - _TC", 31200.0, 0.0), ("Salary Deductions - _TC", "_Test Cost Center - _TC", 0.0, 320.0), ("Salary Deductions - _TC", "_Test Cost Center 2 - _TC", 0.0, 80.0), ) self.assertEqual(je_entries, expected_je)
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
def test_loan(self): branch = "Test Employee Branch" applicant = make_employee("*****@*****.**", company="_Test Company") company = "_Test Company" holiday_list = make_holiday("test holiday for loan") company_doc = frappe.get_doc("Company", company) if not company_doc.default_payroll_payable_account: company_doc.default_payroll_payable_account = frappe.db.get_value( "Account", { "company": company, "root_type": "Liability", "account_type": "" }, "name") company_doc.save() if not frappe.db.exists("Branch", branch): frappe.get_doc({"doctype": "Branch", "branch": branch}).insert() employee_doc = frappe.get_doc("Employee", applicant) employee_doc.branch = branch employee_doc.holiday_list = holiday_list employee_doc.save() salary_structure = "Test Salary Structure for Loan" make_salary_structure( salary_structure, "Monthly", employee=employee_doc.name, company="_Test Company", currency=company_doc.default_currency, ) if not frappe.db.exists("Loan Type", "Car Loan"): create_loan_accounts() create_loan_type( "Car Loan", 500000, 8.4, is_term_loan=1, mode_of_payment="Cash", disbursement_account="Disbursement Account - _TC", payment_account="Payment Account - _TC", loan_account="Loan Account - _TC", interest_income_account="Interest Income Account - _TC", penalty_income_account="Penalty Income Account - _TC", ) loan = create_loan( applicant, "Car Loan", 280000, "Repay Over Number of Periods", 20, posting_date=add_months(nowdate(), -1), ) loan.repay_from_salary = 1 loan.submit() make_loan_disbursement_entry(loan.name, loan.loan_amount, disbursement_date=add_months( nowdate(), -1)) process_loan_interest_accrual_for_term_loans(posting_date=nowdate()) dates = get_start_end_dates("Monthly", nowdate()) make_payroll_entry( company="_Test Company", start_date=dates.start_date, payable_account=company_doc.default_payroll_payable_account, currency=company_doc.default_currency, end_date=dates.end_date, branch=branch, cost_center="Main - _TC", payment_account="Cash - _TC", ) name = frappe.db.get_value("Salary Slip", { "posting_date": nowdate(), "employee": applicant }, "name") salary_slip = frappe.get_doc("Salary Slip", name) for row in salary_slip.loans: if row.loan == loan.name: interest_amount = (280000 * 8.4) / (12 * 100) principal_amount = loan.monthly_repayment_amount - interest_amount self.assertEqual(row.interest_amount, interest_amount) self.assertEqual(row.principal_amount, principal_amount) self.assertEqual(row.total_payment, interest_amount + principal_amount) if salary_slip.docstatus == 0: frappe.delete_doc("Salary Slip", name)