Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions hrms/hooks.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@
"Timesheet": "hrms.overrides.employee_timesheet.EmployeeTimesheet",
"Payment Entry": "hrms.overrides.employee_payment_entry.EmployeePaymentEntry",
"Project": "hrms.overrides.employee_project.EmployeeProject",
"Journal Entry": "hrms.overrides.journal_entry.HRMSJournalEntry",
}

# Document Events
Expand Down
13 changes: 13 additions & 0 deletions hrms/overrides/journal_entry.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import frappe
from frappe import _
from frappe.utils import flt

from erpnext.accounts.doctype.journal_entry.journal_entry import JournalEntry


class HRMSJournalEntry(JournalEntry):
def validate_debit_credit_amount(self):
if not (self.voucher_type == "Exchange Gain Or Loss" and self.multi_currency):
for d in self.get("accounts"):
if not flt(d.debit) and not flt(d.credit) and d.reference_type != "Payroll Entry":
frappe.throw(_("Row {0}: Both Debit and Credit values cannot be zero").format(d.idx))
2 changes: 1 addition & 1 deletion hrms/payroll/doctype/payroll_entry/payroll_entry.py
Original file line number Diff line number Diff line change
Expand Up @@ -852,7 +852,7 @@ def get_accounting_entries_and_payable_amount(
accounting_dimensions,
)

if amt:
if amt or (amt >= 0 and account == self.payroll_payable_account):
accounts.append(row)

return payable_amount
Expand Down
53 changes: 53 additions & 0 deletions hrms/payroll/doctype/payroll_entry/test_payroll_entry.py
Original file line number Diff line number Diff line change
Expand Up @@ -1060,6 +1060,59 @@ def test_status_on_discard(self):
payroll_entry.reload()
self.assertEqual(payroll_entry.status, "Cancelled")

def test_payroll_entry_with_zero_amount(self):
company = frappe.get_doc("Company", "_Test Company")
employee = make_employee("test_zero_amount@payroll.com", company=company.name)

from hrms.payroll.doctype.salary_structure.test_salary_structure import make_salary_structure

earning_comp = create_salary_component("Test Earning", **{"type": "Earning"})
earning_comp.append("accounts", {"company": company.name, "account": "Salary - _TC"})
earning_comp.save()

deduction_comp = create_salary_component("Test Deduction", **{"type": "Deduction"})
deduction_comp.append("accounts", {"company": company.name, "account": "Salary - _TC"})
deduction_comp.save()

make_salary_structure(
"_Test Zero Amount Salary Structure",
"Monthly",
employee,
company=company.name,
other_details={
"earnings": [{"salary_component": earning_comp.name, "amount": 1000}],
"deductions": [{"salary_component": deduction_comp.name, "amount": 1000}],
},
)

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.default_payroll_payable_account,
currency=company.default_currency,
company=company.name,
cost_center="Main - _TC",
)

self.assertEqual(payroll_entry.status, "Submitted")

salary_slip = frappe.db.get_value("Salary Slip", {"payroll_entry": payroll_entry.name}, "name")
self.assertIsNotNone(salary_slip)

salary_slip_doc = frappe.get_doc("Salary Slip", salary_slip)
self.assertEqual(salary_slip_doc.net_pay, 0)
self.assertEqual(salary_slip_doc.gross_pay, 1000)
self.assertEqual(salary_slip_doc.total_deduction, 1000)
self.assertEqual(salary_slip_doc.net_pay, 0)

journal_entry_name = frappe.db.get_value(
"Journal Entry Account",
{"reference_type": "Payroll Entry", "reference_name": payroll_entry.name},
"parent",
)
self.assertIsNotNone(journal_entry_name, "Journal Entry should be created for zero net pay")


def get_payroll_entry(**args):
args = frappe._dict(args)
Expand Down
Loading