mirror of
https://github.com/frappe/erpnext.git
synced 2026-06-02 03:39:11 +00:00
test: Salary Slip operations queuing, failure, and payroll entry status
- fix multicurrency test, remove redundant doc creation
This commit is contained in:
@@ -5,6 +5,7 @@ import unittest
|
|||||||
|
|
||||||
import frappe
|
import frappe
|
||||||
from dateutil.relativedelta import relativedelta
|
from dateutil.relativedelta import relativedelta
|
||||||
|
from frappe.tests.utils import FrappeTestCase
|
||||||
from frappe.utils import add_months
|
from frappe.utils import add_months
|
||||||
|
|
||||||
import erpnext
|
import erpnext
|
||||||
@@ -35,14 +36,12 @@ from erpnext.payroll.doctype.salary_structure.test_salary_structure import (
|
|||||||
test_dependencies = ["Holiday List"]
|
test_dependencies = ["Holiday List"]
|
||||||
|
|
||||||
|
|
||||||
class TestPayrollEntry(unittest.TestCase):
|
class TestPayrollEntry(FrappeTestCase):
|
||||||
@classmethod
|
def setUp(self):
|
||||||
def setUpClass(cls):
|
|
||||||
frappe.db.set_value(
|
frappe.db.set_value(
|
||||||
"Company", erpnext.get_default_company(), "default_holiday_list", "_Test Holiday List"
|
"Company", erpnext.get_default_company(), "default_holiday_list", "_Test Holiday List"
|
||||||
)
|
)
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
for dt in [
|
for dt in [
|
||||||
"Salary Slip",
|
"Salary Slip",
|
||||||
"Salary Component",
|
"Salary Component",
|
||||||
@@ -88,40 +87,40 @@ class TestPayrollEntry(unittest.TestCase):
|
|||||||
currency=company_doc.default_currency,
|
currency=company_doc.default_currency,
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_multi_currency_payroll_entry(self): # pylint: disable=no-self-use
|
def test_multi_currency_payroll_entry(self):
|
||||||
company = erpnext.get_default_company()
|
company = frappe.get_doc("Company", "_Test Company")
|
||||||
employee = make_employee("test_muti_currency_employee@payroll.com", company=company)
|
employee = make_employee(
|
||||||
|
"test_muti_currency_employee@payroll.com", company=company.name, department="Accounts - _TC"
|
||||||
|
)
|
||||||
|
|
||||||
for data in frappe.get_all("Salary Component", fields=["name"]):
|
for data in frappe.get_all("Salary Component", fields=["name"]):
|
||||||
if not frappe.db.get_value(
|
if not frappe.db.get_value(
|
||||||
"Salary Component Account", {"parent": data.name, "company": company}, "name"
|
"Salary Component Account", {"parent": data.name, "company": company.name}, "name"
|
||||||
):
|
):
|
||||||
set_salary_component_account(data.name)
|
set_salary_component_account(data.name)
|
||||||
|
|
||||||
company_doc = frappe.get_doc("Company", company)
|
salary_struct = make_salary_structure(
|
||||||
salary_structure = make_salary_structure(
|
"_Test Multi Currency Salary Structure",
|
||||||
"_Test Multi Currency Salary Structure", "Monthly", company=company, currency="USD"
|
"Monthly",
|
||||||
)
|
employee,
|
||||||
create_salary_structure_assignment(
|
currency="USD",
|
||||||
employee, salary_structure.name, company=company, currency="USD"
|
company=company.name,
|
||||||
)
|
|
||||||
frappe.db.sql(
|
|
||||||
"""delete from `tabSalary Slip` where employee=%s""",
|
|
||||||
(frappe.db.get_value("Employee", {"user_id": "test_muti_currency_employee@payroll.com"})),
|
|
||||||
)
|
|
||||||
salary_slip = get_salary_slip(
|
|
||||||
"test_muti_currency_employee@payroll.com", "Monthly", "_Test Multi Currency Salary Structure"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
frappe.db.delete("Salary Slip", {"employee": employee})
|
||||||
dates = get_start_end_dates("Monthly", nowdate())
|
dates = get_start_end_dates("Monthly", nowdate())
|
||||||
payroll_entry = make_payroll_entry(
|
payroll_entry = make_payroll_entry(
|
||||||
start_date=dates.start_date,
|
start_date=dates.start_date,
|
||||||
end_date=dates.end_date,
|
end_date=dates.end_date,
|
||||||
payable_account=company_doc.default_payroll_payable_account,
|
payable_account=company.default_payroll_payable_account,
|
||||||
currency="USD",
|
currency="USD",
|
||||||
exchange_rate=70,
|
exchange_rate=70,
|
||||||
|
company=company.name,
|
||||||
)
|
)
|
||||||
payroll_entry.make_payment_entry()
|
payroll_entry.make_payment_entry()
|
||||||
|
|
||||||
salary_slip.load_from_db()
|
salary_slip = frappe.db.get_value("Salary Slip", {"payroll_entry": payroll_entry.name})
|
||||||
|
salary_slip = frappe.get_doc("Salary Slip", salary_slip)
|
||||||
|
|
||||||
payroll_je = salary_slip.journal_entry
|
payroll_je = salary_slip.journal_entry
|
||||||
if payroll_je:
|
if payroll_je:
|
||||||
@@ -143,7 +142,7 @@ class TestPayrollEntry(unittest.TestCase):
|
|||||||
self.assertEqual(salary_slip.base_net_pay, payment_entry[0].total_debit)
|
self.assertEqual(salary_slip.base_net_pay, payment_entry[0].total_debit)
|
||||||
self.assertEqual(salary_slip.base_net_pay, payment_entry[0].total_credit)
|
self.assertEqual(salary_slip.base_net_pay, payment_entry[0].total_credit)
|
||||||
|
|
||||||
def test_payroll_entry_with_employee_cost_center(self): # pylint: disable=no-self-use
|
def test_payroll_entry_with_employee_cost_center(self):
|
||||||
for data in frappe.get_all("Salary Component", fields=["name"]):
|
for data in frappe.get_all("Salary Component", fields=["name"]):
|
||||||
if not frappe.db.get_value(
|
if not frappe.db.get_value(
|
||||||
"Salary Component Account", {"parent": data.name, "company": "_Test Company"}, "name"
|
"Salary Component Account", {"parent": data.name, "company": "_Test Company"}, "name"
|
||||||
@@ -356,8 +355,114 @@ class TestPayrollEntry(unittest.TestCase):
|
|||||||
if salary_slip.docstatus == 0:
|
if salary_slip.docstatus == 0:
|
||||||
frappe.delete_doc("Salary Slip", name)
|
frappe.delete_doc("Salary Slip", name)
|
||||||
|
|
||||||
|
def test_salary_slip_operation_queueing(self):
|
||||||
|
# setup
|
||||||
|
company = erpnext.get_default_company()
|
||||||
|
company_doc = frappe.get_doc("Company", company)
|
||||||
|
employee = frappe.db.get_value("Employee", {"company": company})
|
||||||
|
make_salary_structure(
|
||||||
|
"_Test Salary Structure",
|
||||||
|
"Monthly",
|
||||||
|
employee,
|
||||||
|
company=company,
|
||||||
|
currency=company_doc.default_currency,
|
||||||
|
)
|
||||||
|
|
||||||
def make_payroll_entry(**args):
|
# enqueue salary slip creation via payroll entry
|
||||||
|
# Payroll Entry status should change to Queued
|
||||||
|
dates = get_start_end_dates("Monthly", nowdate())
|
||||||
|
payroll_entry = get_payroll_entry_data(
|
||||||
|
start_date=dates.start_date,
|
||||||
|
end_date=dates.end_date,
|
||||||
|
payable_account=company_doc.default_payroll_payable_account,
|
||||||
|
currency=company_doc.default_currency,
|
||||||
|
)
|
||||||
|
frappe.flags.enqueue_payroll_entry = True
|
||||||
|
payroll_entry.create_salary_slips()
|
||||||
|
payroll_entry.reload()
|
||||||
|
|
||||||
|
self.assertEqual(payroll_entry.status, "Queued")
|
||||||
|
frappe.flags.enqueue_payroll_entry = False
|
||||||
|
|
||||||
|
def test_salary_slip_operation_failure(self):
|
||||||
|
# setup
|
||||||
|
company = erpnext.get_default_company()
|
||||||
|
company_doc = frappe.get_doc("Company", company)
|
||||||
|
employee = frappe.db.get_value("Employee", {"company": company})
|
||||||
|
salary_structure = make_salary_structure(
|
||||||
|
"_Test Salary Structure",
|
||||||
|
"Monthly",
|
||||||
|
employee,
|
||||||
|
company=company,
|
||||||
|
currency=company_doc.default_currency,
|
||||||
|
)
|
||||||
|
|
||||||
|
# reset account in component to test submission failure
|
||||||
|
component = frappe.get_doc("Salary Component", salary_structure.earnings[0].salary_component)
|
||||||
|
component.accounts = []
|
||||||
|
component.save()
|
||||||
|
|
||||||
|
# salary slip submission via payroll entry
|
||||||
|
# Payroll Entry status should change to Failed because of the missing account setup
|
||||||
|
dates = get_start_end_dates("Monthly", nowdate())
|
||||||
|
payroll_entry = get_payroll_entry_data(
|
||||||
|
start_date=dates.start_date,
|
||||||
|
end_date=dates.end_date,
|
||||||
|
payable_account=company_doc.default_payroll_payable_account,
|
||||||
|
currency=company_doc.default_currency,
|
||||||
|
)
|
||||||
|
payroll_entry.create_salary_slips()
|
||||||
|
payroll_entry.submit_salary_slips()
|
||||||
|
|
||||||
|
payroll_entry.reload()
|
||||||
|
self.assertEqual(payroll_entry.status, "Failed")
|
||||||
|
self.assertIsNotNone(payroll_entry.error_message)
|
||||||
|
|
||||||
|
# set accounts
|
||||||
|
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"
|
||||||
|
):
|
||||||
|
set_salary_component_account(data.name, company_list=[company])
|
||||||
|
|
||||||
|
# Payroll Entry successful, status should change to Submitted
|
||||||
|
payroll_entry.submit_salary_slips()
|
||||||
|
payroll_entry.reload()
|
||||||
|
self.assertEqual(payroll_entry.status, "Submitted")
|
||||||
|
self.assertEqual(payroll_entry.error_message, "")
|
||||||
|
|
||||||
|
def test_payroll_entry_status(self):
|
||||||
|
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"
|
||||||
|
):
|
||||||
|
set_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())
|
||||||
|
payroll_entry = get_payroll_entry_data(
|
||||||
|
start_date=dates.start_date,
|
||||||
|
end_date=dates.end_date,
|
||||||
|
payable_account=company_doc.default_payroll_payable_account,
|
||||||
|
currency=company_doc.default_currency,
|
||||||
|
)
|
||||||
|
payroll_entry.submit()
|
||||||
|
self.assertEqual(payroll_entry.status, "Submitted")
|
||||||
|
|
||||||
|
payroll_entry.cancel()
|
||||||
|
self.assertEqual(payroll_entry.status, "Cancelled")
|
||||||
|
|
||||||
|
|
||||||
|
def get_payroll_entry_data(**args):
|
||||||
args = frappe._dict(args)
|
args = frappe._dict(args)
|
||||||
|
|
||||||
payroll_entry = frappe.new_doc("Payroll Entry")
|
payroll_entry = frappe.new_doc("Payroll Entry")
|
||||||
@@ -381,7 +486,13 @@ def make_payroll_entry(**args):
|
|||||||
|
|
||||||
payroll_entry.fill_employee_details()
|
payroll_entry.fill_employee_details()
|
||||||
payroll_entry.save()
|
payroll_entry.save()
|
||||||
payroll_entry.create_salary_slips()
|
|
||||||
|
return payroll_entry
|
||||||
|
|
||||||
|
|
||||||
|
def make_payroll_entry(**args):
|
||||||
|
payroll_entry = get_payroll_entry_data(**args)
|
||||||
|
payroll_entry.submit()
|
||||||
payroll_entry.submit_salary_slips()
|
payroll_entry.submit_salary_slips()
|
||||||
if payroll_entry.get_sal_slip_list(ss_status=1):
|
if payroll_entry.get_sal_slip_list(ss_status=1):
|
||||||
payroll_entry.make_payment_entry()
|
payroll_entry.make_payment_entry()
|
||||||
@@ -421,12 +532,3 @@ def make_holiday(holiday_list_name):
|
|||||||
).insert()
|
).insert()
|
||||||
|
|
||||||
return holiday_list_name
|
return holiday_list_name
|
||||||
|
|
||||||
|
|
||||||
def get_salary_slip(user, period, salary_structure):
|
|
||||||
salary_slip = make_employee_salary_slip(user, period, salary_structure)
|
|
||||||
salary_slip.exchange_rate = 70
|
|
||||||
salary_slip.calculate_net_pay()
|
|
||||||
salary_slip.db_update()
|
|
||||||
|
|
||||||
return salary_slip
|
|
||||||
|
|||||||
@@ -169,9 +169,6 @@ def make_salary_structure(
|
|||||||
payroll_period=None,
|
payroll_period=None,
|
||||||
include_flexi_benefits=False,
|
include_flexi_benefits=False,
|
||||||
):
|
):
|
||||||
if test_tax:
|
|
||||||
frappe.db.sql("""delete from `tabSalary Structure` where name=%s""", (salary_structure))
|
|
||||||
|
|
||||||
if frappe.db.exists("Salary Structure", salary_structure):
|
if frappe.db.exists("Salary Structure", salary_structure):
|
||||||
frappe.db.delete("Salary Structure", salary_structure)
|
frappe.db.delete("Salary Structure", salary_structure)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user