From e64e81267941425b781d38437ea3f6fd19240223 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Mon, 29 Aug 2022 18:33:40 +0530 Subject: [PATCH 1/2] fix: Loan Write-off for term loans --- .../doctype/loan_repayment/loan_repayment.py | 1 + .../process_loan_interest_accrual.py | 11 +++++-- .../salary_slip_loan/salary_slip_loan.json | 5 ++-- .../doctype/salary_slip/salary_slip.json | 3 +- .../doctype/salary_slip/salary_slip.py | 30 ++++++++++++++----- 5 files changed, 35 insertions(+), 15 deletions(-) diff --git a/erpnext/loan_management/doctype/loan_repayment/loan_repayment.py b/erpnext/loan_management/doctype/loan_repayment/loan_repayment.py index 2f9f4571f28..19d0d84a46f 100644 --- a/erpnext/loan_management/doctype/loan_repayment/loan_repayment.py +++ b/erpnext/loan_management/doctype/loan_repayment/loan_repayment.py @@ -734,6 +734,7 @@ def get_amounts(amounts, against_loan, posting_date): ) amounts["pending_accrual_entries"] = pending_accrual_entries amounts["unaccrued_interest"] = flt(unaccrued_interest, precision) + amounts["written_off_amount"] = flt(against_loan_doc.written_off_amount, precision) if final_due_date: amounts["due_date"] = final_due_date diff --git a/erpnext/loan_management/doctype/process_loan_interest_accrual/process_loan_interest_accrual.py b/erpnext/loan_management/doctype/process_loan_interest_accrual/process_loan_interest_accrual.py index 81464a36c3d..7872624ce2c 100644 --- a/erpnext/loan_management/doctype/process_loan_interest_accrual/process_loan_interest_accrual.py +++ b/erpnext/loan_management/doctype/process_loan_interest_accrual/process_loan_interest_accrual.py @@ -57,7 +57,7 @@ def process_loan_interest_accrual_for_demand_loans( def process_loan_interest_accrual_for_term_loans(posting_date=None, loan_type=None, loan=None): - if not term_loan_accrual_pending(posting_date or nowdate()): + if not term_loan_accrual_pending(posting_date or nowdate(), loan=loan): return loan_process = frappe.new_doc("Process Loan Interest Accrual") @@ -71,9 +71,14 @@ def process_loan_interest_accrual_for_term_loans(posting_date=None, loan_type=No return loan_process.name -def term_loan_accrual_pending(date): +def term_loan_accrual_pending(date, loan=None): + filters = {"payment_date": ("<=", date), "is_accrued": 0} + + if loan: + filters.update({'parent': loan}) + pending_accrual = frappe.db.get_value( - "Repayment Schedule", {"payment_date": ("<=", date), "is_accrued": 0} + "Repayment Schedule", filters ) return pending_accrual diff --git a/erpnext/loan_management/doctype/salary_slip_loan/salary_slip_loan.json b/erpnext/loan_management/doctype/salary_slip_loan/salary_slip_loan.json index b7b20d945d6..32e281ddf41 100644 --- a/erpnext/loan_management/doctype/salary_slip_loan/salary_slip_loan.json +++ b/erpnext/loan_management/doctype/salary_slip_loan/salary_slip_loan.json @@ -64,7 +64,7 @@ "fieldname": "total_payment", "fieldtype": "Currency", "in_list_view": 1, - "label": "Total Payment", + "label": "Paid Amount", "options": "Company:company:default_currency" }, { @@ -87,7 +87,7 @@ "index_web_pages_for_search": 1, "istable": 1, "links": [], - "modified": "2022-01-31 14:50:14.823213", + "modified": "2022-08-29 08:50:39.030296", "modified_by": "Administrator", "module": "Loan Management", "name": "Salary Slip Loan", @@ -96,6 +96,5 @@ "quick_entry": 1, "sort_field": "modified", "sort_order": "DESC", - "states": [], "track_changes": 1 } \ No newline at end of file diff --git a/erpnext/payroll/doctype/salary_slip/salary_slip.json b/erpnext/payroll/doctype/salary_slip/salary_slip.json index ad00d6d323f..4214c0238c3 100644 --- a/erpnext/payroll/doctype/salary_slip/salary_slip.json +++ b/erpnext/payroll/doctype/salary_slip/salary_slip.json @@ -377,7 +377,6 @@ "fieldtype": "Column Break" }, { - "depends_on": "total_loan_repayment", "fieldname": "loan_repayment", "fieldtype": "Section Break", "label": "Loan Repayment" @@ -647,7 +646,7 @@ "idx": 9, "is_submittable": 1, "links": [], - "modified": "2021-10-08 11:48:47.098248", + "modified": "2022-08-29 08:59:50.819986", "modified_by": "Administrator", "module": "Payroll", "name": "Salary Slip", diff --git a/erpnext/payroll/doctype/salary_slip/salary_slip.py b/erpnext/payroll/doctype/salary_slip/salary_slip.py index a5c892687c5..ee7d965b2a7 100644 --- a/erpnext/payroll/doctype/salary_slip/salary_slip.py +++ b/erpnext/payroll/doctype/salary_slip/salary_slip.py @@ -1379,12 +1379,28 @@ class SalarySlip(TransactionBase): for loan in self.get_loan_details(): amounts = calculate_amounts(loan.name, self.posting_date, "Regular Payment") - if amounts["interest_amount"] or amounts["payable_principal_amount"]: + if (amounts["interest_amount"] or amounts["payable_principal_amount"]) \ + and (amounts["payable_principal_amount"] + amounts["interest_amount"] > amounts["written_off_amount"]): + + print("Ininininin") + if amounts["interest_amount"] > amounts["written_off_amount"]: + amounts["interest_amount"] -= amounts["written_off_amount"] + amounts["written_off_amount"] = 0 + else: + amounts["written_off_amount"] -= amounts["interest_amount"] + amounts["interest_amount"] = 0 + + if amounts["payable_principal_amount"] > amounts["written_off_amount"]: + amounts["payable_principal_amount"] -= amounts["written_off_amount"] + amounts["written_off_amount"] = 0 + else: + amounts["written_off_amount"] -= amounts["payable_principal_amount"] + amounts["payable_principal_amount"] = 0 + self.append( "loans", { "loan": loan.name, - "total_payment": amounts["interest_amount"] + amounts["payable_principal_amount"], "interest_amount": amounts["interest_amount"], "principal_amount": amounts["payable_principal_amount"], "loan_account": loan.loan_account, @@ -1395,7 +1411,7 @@ class SalarySlip(TransactionBase): for payment in self.get("loans"): amounts = calculate_amounts(payment.loan, self.posting_date, "Regular Payment") total_amount = amounts["interest_amount"] + amounts["payable_principal_amount"] - if payment.total_payment > total_amount: + if flt(payment.total_payment) > total_amount: frappe.throw( _( """Row {0}: Paid amount {1} is greater than pending accrued amount {2} against loan {3}""" @@ -1407,10 +1423,10 @@ class SalarySlip(TransactionBase): ) ) - self.total_interest_amount += payment.interest_amount - self.total_principal_amount += payment.principal_amount + self.total_interest_amount += flt(payment.interest_amount) + self.total_principal_amount += flt(payment.principal_amount) - self.total_loan_repayment += payment.total_payment + self.total_loan_repayment += flt(payment.total_payment) def get_loan_details(self): loan_details = frappe.get_all( @@ -1436,7 +1452,7 @@ class SalarySlip(TransactionBase): def make_loan_repayment_entry(self): payroll_payable_account = get_payroll_payable_account(self.company, self.payroll_entry) for loan in self.loans: - if loan.total_payment: + if flt(loan.total_payment) > 0: repayment_entry = create_repayment_entry( loan.loan, self.employee, From 8217c6dd9f119688d5ce7f1f31ccb6a49e282abd Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Tue, 30 Aug 2022 10:24:31 +0530 Subject: [PATCH 2/2] chore: Linting issues and test case fixes --- .../process_loan_interest_accrual.py | 6 ++---- .../payroll/doctype/payroll_entry/test_payroll_entry.py | 2 +- erpnext/payroll/doctype/salary_slip/salary_slip.py | 7 ++++--- erpnext/payroll/doctype/salary_slip/test_salary_slip.py | 3 ++- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/erpnext/loan_management/doctype/process_loan_interest_accrual/process_loan_interest_accrual.py b/erpnext/loan_management/doctype/process_loan_interest_accrual/process_loan_interest_accrual.py index 7872624ce2c..25c72d91a7c 100644 --- a/erpnext/loan_management/doctype/process_loan_interest_accrual/process_loan_interest_accrual.py +++ b/erpnext/loan_management/doctype/process_loan_interest_accrual/process_loan_interest_accrual.py @@ -75,10 +75,8 @@ def term_loan_accrual_pending(date, loan=None): filters = {"payment_date": ("<=", date), "is_accrued": 0} if loan: - filters.update({'parent': loan}) + filters.update({"parent": loan}) - pending_accrual = frappe.db.get_value( - "Repayment Schedule", filters - ) + pending_accrual = frappe.db.get_value("Repayment Schedule", filters) return pending_accrual diff --git a/erpnext/payroll/doctype/payroll_entry/test_payroll_entry.py b/erpnext/payroll/doctype/payroll_entry/test_payroll_entry.py index f3ed5f9e2b9..35cea017e8c 100644 --- a/erpnext/payroll/doctype/payroll_entry/test_payroll_entry.py +++ b/erpnext/payroll/doctype/payroll_entry/test_payroll_entry.py @@ -330,13 +330,13 @@ class TestPayrollEntry(FrappeTestCase): ) 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) diff --git a/erpnext/payroll/doctype/salary_slip/salary_slip.py b/erpnext/payroll/doctype/salary_slip/salary_slip.py index ee7d965b2a7..14a2a3ae398 100644 --- a/erpnext/payroll/doctype/salary_slip/salary_slip.py +++ b/erpnext/payroll/doctype/salary_slip/salary_slip.py @@ -1379,10 +1379,11 @@ class SalarySlip(TransactionBase): for loan in self.get_loan_details(): amounts = calculate_amounts(loan.name, self.posting_date, "Regular Payment") - if (amounts["interest_amount"] or amounts["payable_principal_amount"]) \ - and (amounts["payable_principal_amount"] + amounts["interest_amount"] > amounts["written_off_amount"]): + if (amounts["interest_amount"] or amounts["payable_principal_amount"]) and ( + amounts["payable_principal_amount"] + amounts["interest_amount"] + > amounts["written_off_amount"] + ): - print("Ininininin") if amounts["interest_amount"] > amounts["written_off_amount"]: amounts["interest_amount"] -= amounts["written_off_amount"] amounts["written_off_amount"] = 0 diff --git a/erpnext/payroll/doctype/salary_slip/test_salary_slip.py b/erpnext/payroll/doctype/salary_slip/test_salary_slip.py index 987c1ac281e..e33f8cce4c4 100644 --- a/erpnext/payroll/doctype/salary_slip/test_salary_slip.py +++ b/erpnext/payroll/doctype/salary_slip/test_salary_slip.py @@ -670,9 +670,10 @@ class TestSalarySlip(FrappeTestCase): ss = make_employee_salary_slip( "test_loan_repayment_salary_slip@salary.com", "Monthly", "Test Loan Repayment Salary Structure" ) + + ss.loans[0].total_payment = 592 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))) )