def pull_sal_struct(self): from erpnext.payroll.doctype.salary_structure.salary_structure import make_salary_slip if self.salary_slip_based_on_timesheet: self.salary_structure = self._salary_structure_doc.name self.hour_rate = self._salary_structure_doc.hour_rate self.total_working_hours = sum([d.working_hours or 0.0 for d in self.timesheets]) or 0.0 wages_amount = self.hour_rate * self.total_working_hours self.add_earning_for_hourly_wages(self, self._salary_structure_doc.salary_component, wages_amount) make_salary_slip(self._salary_structure_doc.name, self)
def test_salary_structure_deduction_based_on_gross_pay(self): emp = make_employee("*****@*****.**") sal_struct = make_salary_structure("Salary Structure 2", "Monthly", dont_submit=True) sal_struct.earnings = [sal_struct.earnings[0]] sal_struct.earnings[0].amount_based_on_formula = 1 sal_struct.earnings[0].formula = "base" sal_struct.deductions = [sal_struct.deductions[0]] sal_struct.deductions[0].amount_based_on_formula = 1 sal_struct.deductions[0].condition = "gross_pay > 100" sal_struct.deductions[0].formula = "gross_pay * 0.2" sal_struct.submit() assignment = create_salary_structure_assignment( emp, "Salary Structure 2") ss = make_salary_slip(sal_struct.name, employee=emp) self.assertEqual(assignment.base * 0.2, ss.deductions[0].amount)
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 create_salary_slips_for_payroll_period(employee, salary_structure, payroll_period, deduct_random=True): deducted_dates = [] i = 0 while i < 12: slip = frappe.get_doc({ "doctype": "Salary Slip", "employee": employee, "salary_structure": salary_structure, "frequency": "Monthly" }) if i == 0: posting_date = add_days(payroll_period.start_date, 25) else: posting_date = add_months(posting_date, 1) if i == 11: slip.deduct_tax_for_unsubmitted_tax_exemption_proof = 1 slip.deduct_tax_for_unclaimed_employee_benefits = 1 if deduct_random and not random.randint(0, 2): slip.deduct_tax_for_unsubmitted_tax_exemption_proof = 1 deducted_dates.append(posting_date) slip.posting_date = posting_date slip.start_date = get_first_day(posting_date) slip.end_date = get_last_day(posting_date) doc = make_salary_slip(salary_structure, slip, employee) doc.submit() i += 1 return deducted_dates
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_gratuity_based_on_current_slab_via_additional_salary(self): """ Range | Fraction 5-0 | 1 """ doj = add_days(getdate(), -(6 * 365)) relieving_date = getdate() employee = make_employee( "*****@*****.**", company="_Test Company", date_of_joining=doj, relieving_date=relieving_date, ) sal_slip = create_salary_slip("*****@*****.**") rule = get_gratuity_rule( "Rule Under Unlimited Contract on termination (UAE)") gratuity = create_gratuity(pay_via_salary_slip=1, employee=employee, rule=rule.name) # work experience calculation employee_total_workings_days = (get_datetime(relieving_date) - get_datetime(doj)).days experience = floor(employee_total_workings_days / rule.total_working_days_per_year) self.assertEqual(gratuity.current_work_experience, experience) # amount calculation component_amount = frappe.get_all( "Salary Detail", filters={ "docstatus": 1, "parent": sal_slip, "parentfield": "earnings", "salary_component": "Basic Salary", }, fields=["amount"], limit=1, ) gratuity_amount = component_amount[0].amount * experience self.assertEqual(flt(gratuity_amount, 2), flt(gratuity.amount, 2)) # additional salary creation (Pay via salary slip) self.assertTrue( frappe.db.exists("Additional Salary", {"ref_docname": gratuity.name})) # gratuity should be marked "Paid" on the next salary slip submission salary_slip = make_salary_slip("Test Gratuity", employee=employee) salary_slip.posting_date = getdate() salary_slip.insert() salary_slip.submit() gratuity.reload() self.assertEqual(gratuity.status, "Paid")
def get_component_amt_from_salary_slip(employee, salary_structure, basic_component, hra_component): salary_slip = make_salary_slip(salary_structure, employee=employee, for_preview=1, ignore_permissions=True) basic_amt, hra_amt = 0, 0 for earning in salary_slip.earnings: if earning.salary_component == basic_component: basic_amt = earning.amount elif earning.salary_component == hra_component: hra_amt = earning.amount if basic_amt and hra_amt: return basic_amt, hra_amt return basic_amt, hra_amt
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 check_gross_against_ss(doc, method): from erpnext.payroll.doctype.salary_structure.salary_structure import make_salary_slip ss = make_salary_slip(doc.salary_structure, employee=doc.employee) frappe.errprint(ss.gross_pay) frappe.errprint(doc.base)