Merge pull request #25212 from deepeshgarg007/loan_shortfall_preference

fix: Give first preference to loan security on repayment
This commit is contained in:
Deepesh Garg 2021-04-06 11:06:03 +05:30 committed by GitHub
commit dfe91b5df3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 52 additions and 14 deletions

View File

@ -21,6 +21,7 @@
"interest_payable", "interest_payable",
"payable_amount", "payable_amount",
"column_break_9", "column_break_9",
"shortfall_amount",
"payable_principal_amount", "payable_principal_amount",
"penalty_amount", "penalty_amount",
"amount_paid", "amount_paid",
@ -31,6 +32,7 @@
"column_break_21", "column_break_21",
"reference_date", "reference_date",
"principal_amount_paid", "principal_amount_paid",
"total_penalty_paid",
"total_interest_paid", "total_interest_paid",
"repayment_details", "repayment_details",
"amended_from" "amended_from"
@ -226,12 +228,25 @@
"fieldtype": "Percent", "fieldtype": "Percent",
"label": "Rate Of Interest", "label": "Rate Of Interest",
"read_only": 1 "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, "index_web_pages_for_search": 1,
"is_submittable": 1, "is_submittable": 1,
"links": [], "links": [],
"modified": "2020-11-05 10:06:58.792841", "modified": "2021-04-05 13:45:19.137896",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Loan Management", "module": "Loan Management",
"name": "Loan Repayment", "name": "Loan Repayment",

View File

@ -60,6 +60,12 @@ class LoanRepayment(AccountsController):
if not self.payable_amount: if not self.payable_amount:
self.payable_amount = flt(amounts['payable_amount'], precision) 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'): if amounts.get('due_date'):
self.due_date = amounts.get('due_date') self.due_date = amounts.get('due_date')
@ -69,7 +75,7 @@ class LoanRepayment(AccountsController):
if not self.amount_paid: if not self.amount_paid:
frappe.throw(_("Amount paid cannot be zero")) 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) msg = _("Paid amount cannot be less than {0}").format(self.penalty_amount)
frappe.throw(msg) frappe.throw(msg)
@ -148,11 +154,28 @@ class LoanRepayment(AccountsController):
def allocate_amounts(self, repayment_details): def allocate_amounts(self, repayment_details):
self.set('repayment_details', []) self.set('repayment_details', [])
self.principal_amount_paid = 0 self.principal_amount_paid = 0
total_interest_paid = 0 self.total_penalty_paid = 0
interest_paid = self.amount_paid - self.penalty_amount interest_paid = self.amount_paid
if self.amount_paid - self.penalty_amount > 0: if self.shortfall_amount and self.amount_paid > self.shortfall_amount:
interest_paid = self.amount_paid - self.penalty_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', [])): for lia, amounts in iteritems(repayment_details.get('pending_accrual_entries', [])):
if amounts['interest_amount'] + amounts['payable_principal_amount'] <= interest_paid: if amounts['interest_amount'] + amounts['payable_principal_amount'] <= interest_paid:
interest_amount = amounts['interest_amount'] interest_amount = amounts['interest_amount']
@ -177,7 +200,7 @@ class LoanRepayment(AccountsController):
'paid_principal_amount': paid_principal '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 # no of days for which to accrue interest
# Interest can only be accrued for an entire day and not partial # Interest can only be accrued for an entire day and not partial
if interest_paid > repayment_details['unaccrued_interest']: if interest_paid > repayment_details['unaccrued_interest']:
@ -193,20 +216,20 @@ class LoanRepayment(AccountsController):
interest_paid -= no_of_days * per_day_interest interest_paid -= no_of_days * per_day_interest
self.total_interest_paid = total_interest_paid self.total_interest_paid = total_interest_paid
if interest_paid: if interest_paid > 0:
self.principal_amount_paid += interest_paid self.principal_amount_paid += interest_paid
def make_gl_entries(self, cancel=0, adv_adj=0): def make_gl_entries(self, cancel=0, adv_adj=0):
gle_map = [] gle_map = []
loan_details = frappe.get_doc("Loan", self.against_loan) loan_details = frappe.get_doc("Loan", self.against_loan)
if self.penalty_amount: if self.total_penalty_paid:
gle_map.append( gle_map.append(
self.get_gl_dict({ self.get_gl_dict({
"account": loan_details.loan_account, "account": loan_details.loan_account,
"against": loan_details.payment_account, "against": loan_details.payment_account,
"debit": self.penalty_amount, "debit": self.total_penalty_paid,
"debit_in_account_currency": self.penalty_amount, "debit_in_account_currency": self.total_penalty_paid,
"against_voucher_type": "Loan", "against_voucher_type": "Loan",
"against_voucher": self.against_loan, "against_voucher": self.against_loan,
"remarks": _("Penalty against loan:") + self.against_loan, "remarks": _("Penalty against loan:") + self.against_loan,
@ -221,8 +244,8 @@ class LoanRepayment(AccountsController):
self.get_gl_dict({ self.get_gl_dict({
"account": loan_details.penalty_income_account, "account": loan_details.penalty_income_account,
"against": loan_details.payment_account, "against": loan_details.payment_account,
"credit": self.penalty_amount, "credit": self.total_penalty_paid,
"credit_in_account_currency": self.penalty_amount, "credit_in_account_currency": self.total_penalty_paid,
"against_voucher_type": "Loan", "against_voucher_type": "Loan",
"against_voucher": self.against_loan, "against_voucher": self.against_loan,
"remarks": _("Penalty against loan:") + self.against_loan, "remarks": _("Penalty against loan:") + self.against_loan,

View File

@ -12,7 +12,7 @@ from erpnext.loan_management.doctype.loan_security_unpledge.loan_security_unpled
class LoanSecurityShortfall(Document): class LoanSecurityShortfall(Document):
pass 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_security_shortfall = frappe.db.get_value("Loan Security Shortfall",
{"loan": loan, "status": "Pending"}, ['name', 'shortfall_amount'], as_dict=1) {"loan": loan, "status": "Pending"}, ['name', 'shortfall_amount'], as_dict=1)