Skip to content

Commit 14d2c72

Browse files
Merge pull request #1205 from deepeshgarg007/customer_loan_security_ledger
feat: Customer-level loan security ledger
2 parents e9efaf4 + 52238b8 commit 14d2c72

File tree

5 files changed

+59
-24
lines changed

5 files changed

+59
-24
lines changed

lending/api.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@
77
from frappe import _
88
from frappe.utils import flt, getdate
99

10+
from lending.loan_management.doctype.process_loan_security_shortfall.process_loan_security_shortfall import (
11+
create_process_loan_security_shortfall,
12+
)
13+
1014

1115
@frappe.whitelist()
1216
def get_repayment_schedule(loan_product: str, loan_amount: float, rate_of_interest: float, tenure: int, repayment_frequency: str | None, repayment_start_date: str | None = None) -> list[dict]:
@@ -66,6 +70,7 @@ def update_loan_security_price(data: dict):
6670
"valid_upto": price_details.get("valid_upto")
6771
})
6872

73+
create_process_loan_security_shortfall()
6974
frappe.response["message"] = _("Loan Security Prices updated successfully")
7075

7176
@frappe.whitelist()

lending/loan_management/doctype/loan_security_release/loan_security_release.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
"fieldname": "applicant",
3434
"fieldtype": "Data",
3535
"in_list_view": 1,
36+
"in_standard_filter": 1,
3637
"label": "Applicant",
3738
"reqd": 1,
3839
"search_index": 1
@@ -44,6 +45,7 @@
4445
{
4546
"fieldname": "loan",
4647
"fieldtype": "Link",
48+
"in_standard_filter": 1,
4749
"label": "Loan",
4850
"options": "Loan",
4951
"search_index": 1
@@ -126,7 +128,7 @@
126128
"index_web_pages_for_search": 1,
127129
"is_submittable": 1,
128130
"links": [],
129-
"modified": "2026-03-04 16:46:54.213511",
131+
"modified": "2026-04-12 08:59:16.690887",
130132
"modified_by": "Administrator",
131133
"module": "Loan Management",
132134
"name": "Loan Security Release",

lending/loan_management/doctype/loan_security_release/loan_security_release.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ class LoanSecurityRelease(Document):
2929
applicant_type: DF.Literal["Employee", "Member", "Customer"]
3030
company: DF.Link
3131
description: DF.Text | None
32-
loan: DF.Link
32+
loan: DF.Link | None
3333
reference_no: DF.Data | None
3434
securities: DF.Table[Unpledge]
3535
status: DF.Literal["Requested", "Approved"]

lending/loan_management/report/loan_security_ledger/loan_security_ledger.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,12 @@ frappe.query_reports["Loan Security Ledger"] = {
88
"label": __("Loan"),
99
"fieldtype": "Link",
1010
"options": "Loan",
11-
"reqd": 1,
11+
},
12+
{
13+
"fieldname": "applicant",
14+
"label": __("Applicant"),
15+
"fieldtype": "Link",
16+
"options": "Customer",
1217
},
1318
{
1419
"fieldname": "loan_security",

lending/loan_management/report/loan_security_ledger/loan_security_ledger.py

Lines changed: 44 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33

44
import frappe
55
from frappe import _
6+
from frappe.query_builder import functions as fn
7+
from frappe.query_builder.custom import ConstantColumn
68

79

810
def execute(filters: dict | None = None):
@@ -64,29 +66,50 @@ def get_columns(filters) -> list[dict]:
6466

6567
def get_data(filters) -> list[list]:
6668
loan = filters.get("loan")
69+
applicant = filters.get("applicant")
70+
loan_security = filters.get("loan_security")
71+
72+
if not (loan or applicant):
73+
frappe.throw(_("Please select at least Loan or Applicant to view the ledger"))
74+
6775
balance_qty = 0
6876

69-
unpledges = frappe.db.sql(
70-
"""
71-
SELECT up.loan, "Loan Security Release" as doctype, u.loan_security, u.loan_security_type, u.qty, up.unpledge_time as date
72-
FROM `tabLoan Security Release` up, `tabUnpledge` u
73-
WHERE up.loan = %s
74-
AND u.parent = up.name
75-
AND up.status = 'Approved'
76-
GROUP BY u.loan_security
77-
""", (loan), as_dict=1
78-
)
79-
80-
pledges = frappe.db.sql(
81-
"""
82-
SELECT lsa.loan, "Loan Security Assignment" as doctype, p.loan_security, p.loan_security_type, p.qty, lsa.pledge_time as date
83-
FROM `tabLoan Security Assignment` lsa, `tabPledge` p
84-
WHERE lsa.loan = %s
85-
AND p.parent = lsa.name
86-
AND lsa.status = 'Pledged'
87-
GROUP BY p.loan_security
88-
""", (loan), as_dict=1
89-
)
77+
unpldge_doctype = frappe.qb.DocType("Unpledge")
78+
loan_security_release_doctype = frappe.qb.DocType("Loan Security Release")
79+
80+
pledge_doctype = frappe.qb.DocType("Pledge")
81+
loan_security_assignment_doctype = frappe.qb.DocType("Loan Security Assignment")
82+
83+
unpledge_query = frappe.qb.from_(unpldge_doctype).inner_join(loan_security_release_doctype).on(
84+
unpldge_doctype.parent == loan_security_release_doctype.name
85+
).select(
86+
loan_security_release_doctype.loan, ConstantColumn("Loan Security Release").as_("doctype"), unpldge_doctype.loan_security, fn.Sum(unpldge_doctype.qty).as_("qty"), loan_security_release_doctype.unpledge_time.as_("date"), unpldge_doctype.loan_security_type
87+
).where(loan_security_release_doctype.docstatus == 1).where(loan_security_release_doctype.status == "Approved")
88+
89+
pledge_query = frappe.qb.from_(pledge_doctype).inner_join(loan_security_assignment_doctype).on(
90+
pledge_doctype.parent == loan_security_assignment_doctype.name
91+
).select(
92+
loan_security_assignment_doctype.loan, ConstantColumn("Loan Security Assignment").as_("doctype"), pledge_doctype.loan_security, fn.Sum(pledge_doctype.qty).as_("qty"), loan_security_assignment_doctype.pledge_time.as_("date"), pledge_doctype.loan_security_type
93+
).where(loan_security_assignment_doctype.docstatus == 1).where(loan_security_assignment_doctype.status == "Pledged")
94+
95+
if loan:
96+
unpledge_query = unpledge_query.where(loan_security_release_doctype.loan == loan)
97+
pledge_query = pledge_query.where(loan_security_assignment_doctype.loan == loan)
98+
99+
if applicant:
100+
unpledge_query = unpledge_query.where(loan_security_release_doctype.applicant == applicant)
101+
pledge_query = pledge_query.where(loan_security_assignment_doctype.applicant == applicant)
102+
103+
if loan_security:
104+
unpledge_query = unpledge_query.where(unpldge_doctype.loan_security == loan_security)
105+
pledge_query = pledge_query.where(pledge_doctype.loan_security == loan_security)
106+
107+
if loan_security:
108+
unpledge_query = unpledge_query.where(unpldge_doctype.loan_security == loan_security)
109+
pledge_query = pledge_query.where(pledge_doctype.loan_security == loan_security)
110+
111+
unpledges = unpledge_query.groupby(unpldge_doctype.loan_security).run(as_dict=True)
112+
pledges = pledge_query.groupby(pledge_doctype.loan_security).run(as_dict=True)
90113

91114
result = pledges + unpledges
92115

0 commit comments

Comments
 (0)