diff --git a/erpnext/loan_management/report/loan_interest_report/loan_interest_report.js b/erpnext/loan_management/report/loan_interest_report/loan_interest_report.js index a227b6d797..458c79a1ea 100644 --- a/erpnext/loan_management/report/loan_interest_report/loan_interest_report.js +++ b/erpnext/loan_management/report/loan_interest_report/loan_interest_report.js @@ -11,6 +11,40 @@ frappe.query_reports["Loan Interest Report"] = { "options": "Company", "default": frappe.defaults.get_user_default("Company"), "reqd": 1 - } + }, + { + "fieldname":"applicant_type", + "label": __("Applicant Type"), + "fieldtype": "Select", + "options": ["Customer", "Employee"], + "reqd": 1, + "default": "Customer", + on_change: function() { + frappe.query_report.set_filter_value('applicant', ""); + } + }, + { + "fieldname": "applicant", + "label": __("Applicant"), + "fieldtype": "Dynamic Link", + "get_options": function() { + var applicant_type = frappe.query_report.get_filter_value('applicant_type'); + var applicant = frappe.query_report.get_filter_value('applicant'); + if(applicant && !applicant_type) { + frappe.throw(__("Please select Applicant Type first")); + } + return applicant_type; + } + }, + { + "fieldname":"from_date", + "label": __("From Date"), + "fieldtype": "Date", + }, + { + "fieldname":"to_date", + "label": __("From Date"), + "fieldtype": "Date", + }, ] }; diff --git a/erpnext/loan_management/report/loan_interest_report/loan_interest_report.py b/erpnext/loan_management/report/loan_interest_report/loan_interest_report.py index 9186ce6174..58a7880a45 100644 --- a/erpnext/loan_management/report/loan_interest_report/loan_interest_report.py +++ b/erpnext/loan_management/report/loan_interest_report/loan_interest_report.py @@ -13,12 +13,12 @@ from erpnext.loan_management.report.applicant_wise_loan_security_exposure.applic def execute(filters=None): - columns = get_columns(filters) + columns = get_columns() data = get_active_loan_details(filters) return columns, data -def get_columns(filters): +def get_columns(): columns = [ {"label": _("Loan"), "fieldname": "loan", "fieldtype": "Link", "options": "Loan", "width": 160}, {"label": _("Status"), "fieldname": "status", "fieldtype": "Data", "width": 160}, @@ -70,6 +70,13 @@ def get_columns(filters): "options": "currency", "width": 120, }, + { + "label": _("Accrued Principal"), + "fieldname": "accrued_principal", + "fieldtype": "Currency", + "options": "currency", + "width": 120, + }, { "label": _("Total Repayment"), "fieldname": "total_repayment", @@ -137,11 +144,16 @@ def get_columns(filters): def get_active_loan_details(filters): - - filter_obj = {"status": ("!=", "Closed")} + filter_obj = { + "status": ("!=", "Closed"), + "docstatus": 1, + } if filters.get("company"): filter_obj.update({"company": filters.get("company")}) + if filters.get("applicant"): + filter_obj.update({"applicant": filters.get("applicant")}) + loan_details = frappe.get_all( "Loan", fields=[ @@ -167,8 +179,8 @@ def get_active_loan_details(filters): sanctioned_amount_map = get_sanctioned_amount_map() penal_interest_rate_map = get_penal_interest_rate_map() - payments = get_payments(loan_list) - accrual_map = get_interest_accruals(loan_list) + payments = get_payments(loan_list, filters) + accrual_map = get_interest_accruals(loan_list, filters) currency = erpnext.get_company_currency(filters.get("company")) for loan in loan_details: @@ -183,6 +195,7 @@ def get_active_loan_details(filters): - flt(loan.written_off_amount), "total_repayment": flt(payments.get(loan.loan)), "accrued_interest": flt(accrual_map.get(loan.loan, {}).get("accrued_interest")), + "accrued_principal": flt(accrual_map.get(loan.loan, {}).get("accrued_principal")), "interest_outstanding": flt(accrual_map.get(loan.loan, {}).get("interest_outstanding")), "penalty": flt(accrual_map.get(loan.loan, {}).get("penalty")), "penalty_interest": penal_interest_rate_map.get(loan.loan_type), @@ -212,20 +225,35 @@ def get_sanctioned_amount_map(): ) -def get_payments(loans): +def get_payments(loans, filters): + query_filters = {"against_loan": ("in", loans)} + + if filters.get("from_date"): + query_filters.update({"posting_date": (">=", filters.get("from_date"))}) + + if filters.get("to_date"): + query_filters.update({"posting_date": ("<=", filters.get("to_date"))}) + return frappe._dict( frappe.get_all( "Loan Repayment", fields=["against_loan", "sum(amount_paid)"], - filters={"against_loan": ("in", loans)}, + filters=query_filters, group_by="against_loan", as_list=1, ) ) -def get_interest_accruals(loans): +def get_interest_accruals(loans, filters): accrual_map = {} + query_filters = {"loan": ("in", loans)} + + if filters.get("from_date"): + query_filters.update({"posting_date": (">=", filters.get("from_date"))}) + + if filters.get("to_date"): + query_filters.update({"posting_date": ("<=", filters.get("to_date"))}) interest_accruals = frappe.get_all( "Loan Interest Accrual", @@ -236,8 +264,9 @@ def get_interest_accruals(loans): "penalty_amount", "paid_interest_amount", "accrual_type", + "payable_principal_amount", ], - filters={"loan": ("in", loans)}, + filters=query_filters, order_by="posting_date desc", ) @@ -246,6 +275,7 @@ def get_interest_accruals(loans): entry.loan, { "accrued_interest": 0.0, + "accrued_principal": 0.0, "undue_interest": 0.0, "interest_outstanding": 0.0, "last_accrual_date": "", @@ -270,6 +300,7 @@ def get_interest_accruals(loans): accrual_map[entry.loan]["undue_interest"] += entry.interest_amount - entry.paid_interest_amount accrual_map[entry.loan]["accrued_interest"] += entry.interest_amount + accrual_map[entry.loan]["accrued_principal"] += entry.payable_principal_amount if last_accrual_date and getdate(entry.posting_date) == last_accrual_date: accrual_map[entry.loan]["penalty"] = entry.penalty_amount diff --git a/erpnext/loan_management/workspace/loans/loans.json b/erpnext/loan_management/workspace/loans/loans.json new file mode 100644 index 0000000000..c65be4efae --- /dev/null +++ b/erpnext/loan_management/workspace/loans/loans.json @@ -0,0 +1,315 @@ +{ + "charts": [], + "content": "[{\"id\":\"_38WStznya\",\"type\":\"header\",\"data\":{\"text\":\"Your Shortcuts\",\"col\":12}},{\"id\":\"t7o_K__1jB\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Loan Application\",\"col\":3}},{\"id\":\"IRiNDC6w1p\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Loan\",\"col\":3}},{\"id\":\"xbbo0FYbq0\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Dashboard\",\"col\":3}},{\"id\":\"7ZL4Bro-Vi\",\"type\":\"spacer\",\"data\":{\"col\":12}},{\"id\":\"yhyioTViZ3\",\"type\":\"header\",\"data\":{\"text\":\"Reports & Masters\",\"col\":12}},{\"id\":\"oYFn4b1kSw\",\"type\":\"card\",\"data\":{\"card_name\":\"Loan\",\"col\":4}},{\"id\":\"vZepJF5tl9\",\"type\":\"card\",\"data\":{\"card_name\":\"Loan Processes\",\"col\":4}},{\"id\":\"k-393Mjhqe\",\"type\":\"card\",\"data\":{\"card_name\":\"Disbursement and Repayment\",\"col\":4}},{\"id\":\"6crJ0DBiBJ\",\"type\":\"card\",\"data\":{\"card_name\":\"Loan Security\",\"col\":4}},{\"id\":\"Um5YwxVLRJ\",\"type\":\"card\",\"data\":{\"card_name\":\"Reports\",\"col\":4}}]", + "creation": "2020-03-12 16:35:55.299820", + "docstatus": 0, + "doctype": "Workspace", + "for_user": "", + "hide_custom": 0, + "icon": "loan", + "idx": 0, + "is_hidden": 0, + "label": "Loans", + "links": [ + { + "hidden": 0, + "is_query_report": 0, + "label": "Loan", + "link_count": 0, + "onboard": 0, + "type": "Card Break" + }, + { + "dependencies": "", + "hidden": 0, + "is_query_report": 0, + "label": "Loan Type", + "link_count": 0, + "link_to": "Loan Type", + "link_type": "DocType", + "onboard": 0, + "type": "Link" + }, + { + "dependencies": "", + "hidden": 0, + "is_query_report": 0, + "label": "Loan Application", + "link_count": 0, + "link_to": "Loan Application", + "link_type": "DocType", + "onboard": 0, + "type": "Link" + }, + { + "dependencies": "", + "hidden": 0, + "is_query_report": 0, + "label": "Loan", + "link_count": 0, + "link_to": "Loan", + "link_type": "DocType", + "onboard": 0, + "type": "Link" + }, + { + "hidden": 0, + "is_query_report": 0, + "label": "Loan Processes", + "link_count": 0, + "onboard": 0, + "type": "Card Break" + }, + { + "dependencies": "", + "hidden": 0, + "is_query_report": 0, + "label": "Process Loan Security Shortfall", + "link_count": 0, + "link_to": "Process Loan Security Shortfall", + "link_type": "DocType", + "onboard": 0, + "type": "Link" + }, + { + "dependencies": "", + "hidden": 0, + "is_query_report": 0, + "label": "Process Loan Interest Accrual", + "link_count": 0, + "link_to": "Process Loan Interest Accrual", + "link_type": "DocType", + "onboard": 0, + "type": "Link" + }, + { + "hidden": 0, + "is_query_report": 0, + "label": "Disbursement and Repayment", + "link_count": 0, + "onboard": 0, + "type": "Card Break" + }, + { + "dependencies": "", + "hidden": 0, + "is_query_report": 0, + "label": "Loan Disbursement", + "link_count": 0, + "link_to": "Loan Disbursement", + "link_type": "DocType", + "onboard": 0, + "type": "Link" + }, + { + "dependencies": "", + "hidden": 0, + "is_query_report": 0, + "label": "Loan Repayment", + "link_count": 0, + "link_to": "Loan Repayment", + "link_type": "DocType", + "onboard": 0, + "type": "Link" + }, + { + "dependencies": "", + "hidden": 0, + "is_query_report": 0, + "label": "Loan Write Off", + "link_count": 0, + "link_to": "Loan Write Off", + "link_type": "DocType", + "onboard": 0, + "type": "Link" + }, + { + "dependencies": "", + "hidden": 0, + "is_query_report": 0, + "label": "Loan Interest Accrual", + "link_count": 0, + "link_to": "Loan Interest Accrual", + "link_type": "DocType", + "onboard": 0, + "type": "Link" + }, + { + "hidden": 0, + "is_query_report": 0, + "label": "Loan Security", + "link_count": 0, + "onboard": 0, + "type": "Card Break" + }, + { + "dependencies": "", + "hidden": 0, + "is_query_report": 0, + "label": "Loan Security Type", + "link_count": 0, + "link_to": "Loan Security Type", + "link_type": "DocType", + "onboard": 0, + "type": "Link" + }, + { + "dependencies": "", + "hidden": 0, + "is_query_report": 0, + "label": "Loan Security Price", + "link_count": 0, + "link_to": "Loan Security Price", + "link_type": "DocType", + "onboard": 0, + "type": "Link" + }, + { + "dependencies": "", + "hidden": 0, + "is_query_report": 0, + "label": "Loan Security", + "link_count": 0, + "link_to": "Loan Security", + "link_type": "DocType", + "onboard": 0, + "type": "Link" + }, + { + "dependencies": "", + "hidden": 0, + "is_query_report": 0, + "label": "Loan Security Pledge", + "link_count": 0, + "link_to": "Loan Security Pledge", + "link_type": "DocType", + "onboard": 0, + "type": "Link" + }, + { + "dependencies": "", + "hidden": 0, + "is_query_report": 0, + "label": "Loan Security Unpledge", + "link_count": 0, + "link_to": "Loan Security Unpledge", + "link_type": "DocType", + "onboard": 0, + "type": "Link" + }, + { + "dependencies": "", + "hidden": 0, + "is_query_report": 0, + "label": "Loan Security Shortfall", + "link_count": 0, + "link_to": "Loan Security Shortfall", + "link_type": "DocType", + "onboard": 0, + "type": "Link" + }, + { + "hidden": 0, + "is_query_report": 0, + "label": "Reports", + "link_count": 6, + "onboard": 0, + "type": "Card Break" + }, + { + "dependencies": "", + "hidden": 0, + "is_query_report": 1, + "label": "Loan Repayment and Closure", + "link_count": 0, + "link_to": "Loan Repayment and Closure", + "link_type": "Report", + "onboard": 0, + "type": "Link" + }, + { + "dependencies": "", + "hidden": 0, + "is_query_report": 1, + "label": "Loan Security Status", + "link_count": 0, + "link_to": "Loan Security Status", + "link_type": "Report", + "onboard": 0, + "type": "Link" + }, + { + "hidden": 0, + "is_query_report": 1, + "label": "Loan Interest Report", + "link_count": 0, + "link_to": "Loan Interest Report", + "link_type": "Report", + "onboard": 0, + "type": "Link" + }, + { + "hidden": 0, + "is_query_report": 1, + "label": "Loan Security Exposure", + "link_count": 0, + "link_to": "Loan Security Exposure", + "link_type": "Report", + "onboard": 0, + "type": "Link" + }, + { + "hidden": 0, + "is_query_report": 1, + "label": "Applicant-Wise Loan Security Exposure", + "link_count": 0, + "link_to": "Applicant-Wise Loan Security Exposure", + "link_type": "Report", + "onboard": 0, + "type": "Link" + }, + { + "hidden": 0, + "is_query_report": 1, + "label": "Loan Security Status", + "link_count": 0, + "link_to": "Loan Security Status", + "link_type": "Report", + "onboard": 0, + "type": "Link" + } + ], + "modified": "2023-01-31 19:47:13.114415", + "modified_by": "Administrator", + "module": "Loan Management", + "name": "Loans", + "owner": "Administrator", + "parent_page": "", + "public": 1, + "quick_lists": [], + "restrict_to_domain": "", + "roles": [], + "sequence_id": 16.0, + "shortcuts": [ + { + "color": "Green", + "format": "{} Open", + "label": "Loan Application", + "link_to": "Loan Application", + "stats_filter": "{ \"status\": \"Open\" }", + "type": "DocType" + }, + { + "label": "Loan", + "link_to": "Loan", + "type": "DocType" + }, + { + "doc_view": "", + "label": "Dashboard", + "link_to": "Loan Dashboard", + "type": "Dashboard" + } + ], + "title": "Loans" +} \ No newline at end of file