From 015fd681ec32529b7b10bfebf84f6480a2739ae5 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Tue, 6 Apr 2021 00:49:46 +0530 Subject: [PATCH] fix: Give first preference to loan security on repayment --- .../loan_repayment/loan_repayment.json | 17 ++++++- .../doctype/loan_repayment/loan_repayment.py | 47 ++++++++++++++----- .../loan_security_shortfall.py | 2 +- 3 files changed, 52 insertions(+), 14 deletions(-) diff --git a/erpnext/loan_management/doctype/loan_repayment/loan_repayment.json b/erpnext/loan_management/doctype/loan_repayment/loan_repayment.json index 2b5df4be24..86ea59dc24 100644 --- a/erpnext/loan_management/doctype/loan_repayment/loan_repayment.json +++ b/erpnext/loan_management/doctype/loan_repayment/loan_repayment.json @@ -21,6 +21,7 @@ "interest_payable", "payable_amount", "column_break_9", + "shortfall_amount", "payable_principal_amount", "penalty_amount", "amount_paid", @@ -31,6 +32,7 @@ "column_break_21", "reference_date", "principal_amount_paid", + "total_penalty_paid", "total_interest_paid", "repayment_details", "amended_from" @@ -226,12 +228,25 @@ "fieldtype": "Percent", "label": "Rate Of Interest", "read_only": 1 + }, + { + "fieldname": "shortfall_amount", + "fieldtype": "Currency", + "label": "Shortfall Amount", + "options": "Company:company:default_currency", + "read_only": 1 + }, + { + "fieldname": "total_penalty_paid", + "fieldtype": "Currency", + "label": "Total Penalty Paid", + "options": "Company:company:default_currency" } ], "index_web_pages_for_search": 1, "is_submittable": 1, "links": [], - "modified": "2020-11-05 10:06:58.792841", + "modified": "2021-04-05 13:45:19.137896", "modified_by": "Administrator", "module": "Loan Management", "name": "Loan Repayment", diff --git a/erpnext/loan_management/doctype/loan_repayment/loan_repayment.py b/erpnext/loan_management/doctype/loan_repayment/loan_repayment.py index bac06c4e9e..a88e183ead 100644 --- a/erpnext/loan_management/doctype/loan_repayment/loan_repayment.py +++ b/erpnext/loan_management/doctype/loan_repayment/loan_repayment.py @@ -60,6 +60,12 @@ class LoanRepayment(AccountsController): if not self.payable_amount: self.payable_amount = flt(amounts['payable_amount'], precision) + shortfall_amount = flt(frappe.db.get_value('Loan Security Shortfall', {'loan': self.against_loan, 'status': 'Pending'}, + 'shortfall_amount')) + + if shortfall_amount: + self.shortfall_amount = shortfall_amount + if amounts.get('due_date'): self.due_date = amounts.get('due_date') @@ -69,7 +75,7 @@ class LoanRepayment(AccountsController): if not self.amount_paid: frappe.throw(_("Amount paid cannot be zero")) - if self.amount_paid < self.penalty_amount: + if not self.shortfall_amount and self.amount_paid < self.penalty_amount: msg = _("Paid amount cannot be less than {0}").format(self.penalty_amount) frappe.throw(msg) @@ -148,11 +154,28 @@ class LoanRepayment(AccountsController): def allocate_amounts(self, repayment_details): self.set('repayment_details', []) self.principal_amount_paid = 0 - total_interest_paid = 0 - interest_paid = self.amount_paid - self.penalty_amount + self.total_penalty_paid = 0 + interest_paid = self.amount_paid - if self.amount_paid - self.penalty_amount > 0: - interest_paid = self.amount_paid - self.penalty_amount + if self.shortfall_amount and self.amount_paid > self.shortfall_amount: + self.principal_amount_paid = self.shortfall_amount + elif self.shortfall_amount: + self.principal_amount_paid = self.amount_paid + + interest_paid -= self.principal_amount_paid + + if interest_paid > 0: + if self.penalty_amount and interest_paid > self.penalty_amount: + self.total_penalty_paid = self.penalty_amount + elif self.penalty_amount: + self.total_penalty_paid = interest_paid + + interest_paid -= self.total_penalty_paid + + total_interest_paid = 0 + # interest_paid = self.amount_paid - self.principal_amount_paid - self.penalty_amount + + if interest_paid > 0: for lia, amounts in iteritems(repayment_details.get('pending_accrual_entries', [])): if amounts['interest_amount'] + amounts['payable_principal_amount'] <= interest_paid: interest_amount = amounts['interest_amount'] @@ -177,7 +200,7 @@ class LoanRepayment(AccountsController): 'paid_principal_amount': paid_principal }) - if repayment_details['unaccrued_interest'] and interest_paid: + if repayment_details['unaccrued_interest'] and interest_paid > 0: # no of days for which to accrue interest # Interest can only be accrued for an entire day and not partial if interest_paid > repayment_details['unaccrued_interest']: @@ -193,20 +216,20 @@ class LoanRepayment(AccountsController): interest_paid -= no_of_days * per_day_interest self.total_interest_paid = total_interest_paid - if interest_paid: + if interest_paid > 0: self.principal_amount_paid += interest_paid def make_gl_entries(self, cancel=0, adv_adj=0): gle_map = [] loan_details = frappe.get_doc("Loan", self.against_loan) - if self.penalty_amount: + if self.total_penalty_paid: gle_map.append( self.get_gl_dict({ "account": loan_details.loan_account, "against": loan_details.payment_account, - "debit": self.penalty_amount, - "debit_in_account_currency": self.penalty_amount, + "debit": self.total_penalty_paid, + "debit_in_account_currency": self.total_penalty_paid, "against_voucher_type": "Loan", "against_voucher": self.against_loan, "remarks": _("Penalty against loan:") + self.against_loan, @@ -221,8 +244,8 @@ class LoanRepayment(AccountsController): self.get_gl_dict({ "account": loan_details.penalty_income_account, "against": loan_details.payment_account, - "credit": self.penalty_amount, - "credit_in_account_currency": self.penalty_amount, + "credit": self.total_penalty_paid, + "credit_in_account_currency": self.total_penalty_paid, "against_voucher_type": "Loan", "against_voucher": self.against_loan, "remarks": _("Penalty against loan:") + self.against_loan, diff --git a/erpnext/loan_management/doctype/loan_security_shortfall/loan_security_shortfall.py b/erpnext/loan_management/doctype/loan_security_shortfall/loan_security_shortfall.py index b5e78981d0..ada3a679f9 100644 --- a/erpnext/loan_management/doctype/loan_security_shortfall/loan_security_shortfall.py +++ b/erpnext/loan_management/doctype/loan_security_shortfall/loan_security_shortfall.py @@ -12,7 +12,7 @@ from erpnext.loan_management.doctype.loan_security_unpledge.loan_security_unpled class LoanSecurityShortfall(Document): pass -def update_shortfall_status(loan, security_value): +def update_shortfall_status(loan, security_value, on_cancel=0): loan_security_shortfall = frappe.db.get_value("Loan Security Shortfall", {"loan": loan, "status": "Pending"}, ['name', 'shortfall_amount'], as_dict=1)