Skip to content

Commit

Permalink
Merge branch 'develop' into loan_category
Browse files Browse the repository at this point in the history
  • Loading branch information
anandbaburajan authored Sep 22, 2023
2 parents 9255145 + 14ea3e3 commit 56acc62
Show file tree
Hide file tree
Showing 81 changed files with 3,327 additions and 2,293 deletions.
12 changes: 12 additions & 0 deletions .git-blame-ignore-revs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Since version 2.23 (released in August 2019), git-blame has a feature
# to ignore or bypass certain commits.
#
# This file contains a list of commits that are not likely what you
# are looking for in a blame, such as mass reformatting or renaming.
# You can set this file as a default ignore file for blame by running
# the following command.
#
# $ git config blame.ignoreRevsFile .git-blame-ignore-revs

# This commit just formats inconsistent doctype jsons
7755c1d141ac081f5f6c2ba215e25a44e06e2460
7 changes: 2 additions & 5 deletions lending/hooks.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@
"daily_long": [
"lending.loan_management.doctype.process_loan_security_shortfall.process_loan_security_shortfall.create_process_loan_security_shortfall",
"lending.loan_management.doctype.process_loan_interest_accrual.process_loan_interest_accrual.process_loan_interest_accrual_for_term_loans",
"lending.loan_management.doctype.process_loan_asset_classification.process_loan_asset_classification.create_process_loan_asset_classification",
"lending.loan_management.doctype.process_loan_classification.process_loan_classification.create_process_loan_classification",
],
"monthly_long": [
"lending.loan_management.doctype.process_loan_interest_accrual.process_loan_interest_accrual.process_loan_interest_accrual_for_demand_loans",
Expand All @@ -148,10 +148,7 @@

# Overriding Methods
# ------------------------------

get_matching_vouchers_for_bank_reconciliation = (
"lending.loan_management.utils.get_matching_vouchers_for_bank_reconciliation"
)
get_matching_queries = "lending.loan_management.utils.get_matching_queries"

get_amounts_not_reflected_in_system_for_bank_reconciliation_statement = "lending.loan_management.utils.get_amounts_not_reflected_in_system_for_bank_reconciliation_statement"

Expand Down
45 changes: 39 additions & 6 deletions lending/install.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,17 @@
}
],
"Company": [
{
"fieldname": "loan_tab",
"fieldtype": "Tab Break",
"label": "Loan",
"insert_after": "expenses_included_in_valuation",
},
{
"fieldname": "loan_settings",
"label": "Loan Settings",
"fieldtype": "Section Break",
"insert_after": "exception_budget_approver_role",
"insert_after": "loan_tab",
},
{
"fieldname": "loan_restructure_limit",
Expand All @@ -33,10 +39,23 @@
"fieldtype": "Int",
"insert_after": "loan_restructure_limit",
},
{
"fieldname": "interest_day_count_convention",
"label": "Interest Day-Count Convention",
"fieldtype": "Select",
"options": "Actual/365\nActual/Actual\n30/365\n30/360\nActual/360",
"insert_after": "watch_period_post_loan_restructure_in_days",
},
{
"fieldname": "min_bpi_application_days",
"label": "Minimum Days for Broken Period Interest Application",
"fieldtype": "Int",
"insert_after": "interest_day_count_convention",
},
{
"fieldname": "loan_column_break",
"fieldtype": "Column Break",
"insert_after": "watch_period_post_loan_restructure_in_days",
"insert_after": "min_bpi_application_days",
},
{
"fieldname": "collection_offset_logic_based_on",
Expand Down Expand Up @@ -65,18 +84,32 @@
"options": "IP...IP...IP...CCC\nPPP...III...CCC",
"insert_after": "collection_offset_sequence_for_sub_standard_asset",
},
{
"fieldname": "collection_offset_sequence_for_written_off_asset",
"label": "Collection Offset Sequence for Written Off Asset",
"fieldtype": "Select",
"options": "IP...IP...IP...CCC\nPPP...III...CCC",
"insert_after": "collection_offset_sequence_for_standard_asset",
},
{
"fieldname": "loan_section_break_2",
"fieldtype": "Section Break",
"insert_after": "collection_offset_sequence_for_standard_asset",
"insert_after": "collection_offset_sequence_for_written_off_asset",
},
{
"fieldname": "asset_classification_ranges",
"label": "Asset Classification Ranges",
"fieldname": "loan_classification_ranges",
"label": "Loan Classification Ranges",
"fieldtype": "Table",
"options": "Loan Asset Classification Range",
"options": "Loan Classification Range",
"insert_after": "loan_section_break_2",
},
{
"fieldname": "irac_provisioning_configuration",
"label": "IRAC Provisioning Configuration",
"fieldtype": "Table",
"options": "Loan IRAC Provisioning Configuration",
"insert_after": "loan_classification_ranges",
},
],
"Customer": [
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"loan",
"posting_date",
"days_past_due",
"process_loan_asset_classification"
"process_loan_classification"
],
"fields": [
{
Expand All @@ -32,16 +32,16 @@
"read_only": 1
},
{
"fieldname": "process_loan_asset_classification",
"fieldname": "process_loan_classification",
"fieldtype": "Link",
"label": "Process Loan Asset Classification",
"options": "Process Loan Asset Classification",
"label": "Process Loan Classification",
"options": "Process Loan Classification",
"read_only": 1
}
],
"in_create": 1,
"links": [],
"modified": "2023-08-25 15:37:21.206963",
"modified": "2023-09-14 20:29:11.095918",
"modified_by": "Administrator",
"module": "Loan Management",
"name": "Days Past Due Log",
Expand Down
1 change: 0 additions & 1 deletion lending/loan_management/doctype/loan/loan.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ frappe.ui.form.on('Loan', {
frm.set_query("loan_type", function () {
return {
"filters": {
"docstatus": 1,
"company": frm.doc.company
}
};
Expand Down
51 changes: 21 additions & 30 deletions lending/loan_management/doctype/loan/loan.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,10 @@
"monthly_repayment_amount",
"repayment_start_date",
"is_term_loan",
"loan_asset_classification_details_section",
"loan_classification_details_section",
"days_past_due",
"asset_classification_code",
"asset_classification_name",
"classification_code",
"classification_name",
"column_break_zpe2",
"loan_restructure_count",
"watch_period_end_date",
Expand Down Expand Up @@ -168,8 +168,7 @@
"depends_on": "is_term_loan",
"fieldname": "repayment_start_date",
"fieldtype": "Date",
"label": "Repayment Start Date",
"mandatory_depends_on": "is_term_loan"
"label": "Repayment Start Date"
},
{
"fieldname": "column_break_11",
Expand Down Expand Up @@ -427,22 +426,6 @@
"fieldtype": "Check",
"label": "Manual NPA"
},
{
"fieldname": "asset_classification_code",
"fieldtype": "Select",
"label": "Asset Classification Code",
"no_copy": 1,
"options": "\nSMA-0\nSMA-1\nSMA-2\nD1\nD2\nD3",
"read_only": 1
},
{
"fieldname": "asset_classification_name",
"fieldtype": "Select",
"label": "Asset Classification Name",
"no_copy": 1,
"options": "\nSpecial Mention Account - 0\nSpecial Mention Account - 1\nSpecial Mention Account - 2\nSubstandard Asset\nDoubtful Asset\nLoss Asset",
"read_only": 1
},
{
"fieldname": "branch",
"fieldtype": "Link",
Expand All @@ -455,11 +438,6 @@
"label": "Loan Restructure Count",
"read_only": 1
},
{
"fieldname": "loan_asset_classification_details_section",
"fieldtype": "Section Break",
"label": "Loan Asset Classification Details"
},
{
"fieldname": "column_break_zpe2",
"fieldtype": "Column Break"
Expand All @@ -477,12 +455,25 @@
"read_only": 1
},
{
"fetch_from": "loan_type.loan_category",
"fieldname": "loan_category",
"fieldname": "classification_code",
"fieldtype": "Link",
"label": "Loan Category",
"options": "Loan Category",
"label": "Classification Code",
"no_copy": 1,
"options": "Loan Classification",
"read_only": 1
},
{
"fetch_from": "classification_code.classification_name",
"fieldname": "classification_name",
"fieldtype": "Data",
"label": "Classification Name",
"no_copy": 1,
"read_only": 1
},
{
"fieldname": "loan_classification_details_section",
"fieldtype": "Section Break",
"label": "Loan Classification Details"
}
],
"index_web_pages_for_search": 1,
Expand Down
63 changes: 43 additions & 20 deletions lending/loan_management/doctype/loan/loan.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import frappe
from frappe import _
from frappe.query_builder import Order
from frappe.utils import date_diff, flt, getdate, now_datetime, nowdate
from frappe.utils import add_days, date_diff, flt, get_last_day, getdate, now_datetime, nowdate

import erpnext
from erpnext.accounts.doctype.journal_entry.journal_entry import get_payment_entry
Expand All @@ -26,6 +26,8 @@ def validate(self):
self.validate_cost_center()
self.validate_accounts()
self.check_sanctioned_amount_limit()
self.set_cyclic_date()

if self.is_term_loan and not self.is_new():
self.update_draft_schedule()

Expand Down Expand Up @@ -60,6 +62,19 @@ def validate_cost_center(self):
if not self.cost_center:
frappe.throw(_("Cost center is mandatory for loans having rate of interest greater than 0"))

def set_cyclic_date(self):
if self.repayment_schedule_type == "Monthly as per cycle date":
cycle_day = frappe.db.get_value("Loan Type", self.loan_type, "cyclic_day_of_the_month")
last_day_of_month = get_last_day(self.posting_date)
cyclic_date = add_days(last_day_of_month, cycle_day)

broken_period_limit = frappe.db.get_value("Company", self.company, "min_bpi_application_days")
broken_period_days = date_diff(cyclic_date, self.posting_date)
if broken_period_days < broken_period_limit:
cyclic_date = add_days(get_last_day(cyclic_date), cycle_day)

self.repayment_start_date = cyclic_date

def on_submit(self):
self.link_loan_security_pledge()
# Interest accrual for backdated term loans
Expand Down Expand Up @@ -549,7 +564,7 @@ def make_refund_jv(loan, amount=0, reference_number=None, reference_date=None, s

@frappe.whitelist()
def update_days_past_due_in_loans(
posting_date=None, loan_type=None, loan_name=None, process_loan_asset_classification=None
posting_date=None, loan_type=None, loan_name=None, process_loan_classification=None
):
"""Update days past due in loans"""
posting_date = posting_date or getdate()
Expand Down Expand Up @@ -579,7 +594,7 @@ def update_days_past_due_in_loans(
posting_date or getdate(),
)

create_dpd_record(loan.loan, posting_date, days_past_due, process_loan_asset_classification)
create_dpd_record(loan.loan, posting_date, days_past_due, process_loan_classification)
checked_loans.append(loan.loan)

open_loans_with_no_overdue = []
Expand All @@ -601,19 +616,19 @@ def update_days_past_due_in_loans(
d.name, d.company, d.applicant_type, d.applicant, 0, 0, posting_date or getdate()
)

create_dpd_record(d.name, posting_date, 0, process_loan_asset_classification)
create_dpd_record(d.name, posting_date, 0, process_loan_classification)


def restore_pervious_dpd_state(applicant_type, applicant, repayment_reference):
pac = frappe.db.get_value(
"Process Loan Asset Classification",
"Process Loan Classification",
{"payment_reference": repayment_reference},
"previous_process",
)
for d in frappe.db.get_all(
"Days Past Due Log",
filters={
"process_loan_asset_classification": pac,
"process_loan_classification": pac,
"applicant_type": applicant_type,
"applicant": applicant,
},
Expand All @@ -622,30 +637,32 @@ def restore_pervious_dpd_state(applicant_type, applicant, repayment_reference):
frappe.db.set_value("Loan", d.loan, "days_past_due", d.days_past_due)


def create_dpd_record(loan, posting_date, days_past_due, process_loan_asset_classification=None):
def create_dpd_record(loan, posting_date, days_past_due, process_loan_classification=None):
frappe.get_doc(
{
"doctype": "Days Past Due Log",
"loan": loan,
"posting_date": posting_date,
"days_past_due": days_past_due,
"process_loan_asset_classification": process_loan_asset_classification,
"process_loan_classification": process_loan_classification,
}
).insert(ignore_permissions=True)


def update_loan_and_customer_status(
loan, company, applicant_type, applicant, days_past_due, is_npa, posting_date
):
asset_code, asset_name = get_asset_classification_code_and_name(days_past_due, company)
classification_code, classification_name = get_classification_code_and_name(
days_past_due, company
)

frappe.db.set_value(
"Loan",
loan,
{
"days_past_due": days_past_due,
"asset_classification_code": asset_code,
"asset_classification_name": asset_name,
"classification_code": classification_code,
"classification_name": classification_name,
},
)

Expand Down Expand Up @@ -720,21 +737,27 @@ def update_watch_period_date_for_all_loans(watch_period_end_date, applicant_type
).run()


def get_asset_classification_code_and_name(days_past_due, company):
asset_code = ""
asset_name = ""
def get_classification_code_and_name(days_past_due, company):
classification_code = ""
classification_name = ""

ranges = frappe.get_all(
"Loan Asset Classification Range",
fields=["min_range", "max_range", "asset_classification_code", "asset_classification_name"],
"Loan Classification Range",
fields=[
"min_dpd_range",
"max_dpd_range",
"classification_code",
"classification_name",
],
filters={"parent": company},
order_by="min_range",
order_by="min_dpd_range",
)

for range in ranges:
if range.min_range <= days_past_due <= range.max_range:
return range.asset_classification_code, range.asset_classification_name
if range.min_dpd_range <= days_past_due <= range.max_dpd_range:
return range.classification_code, range.classification_name

return asset_code, asset_name
return classification_code, classification_name


def get_pending_loan_interest_accruals(
Expand Down
Loading

0 comments on commit 56acc62

Please sign in to comment.