fix: UX fixes in loan (#18220)
* fix: UX fixes in loan * Update loan.py
This commit is contained in:
parent
af88e15e92
commit
bd055a858c
@ -1,69 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors
|
|
||||||
# For license information, please see license.txt
|
|
||||||
|
|
||||||
from __future__ import unicode_literals
|
|
||||||
import frappe, math
|
|
||||||
from frappe import _
|
|
||||||
from frappe.utils import flt, rounded
|
|
||||||
from frappe.model.mapper import get_mapped_doc
|
|
||||||
from frappe.model.document import Document
|
|
||||||
|
|
||||||
from erpnext.hr.doctype.employee_loan.employee_loan import get_monthly_repayment_amount, check_repayment_method
|
|
||||||
|
|
||||||
class EmployeeLoanApplication(Document):
|
|
||||||
def validate(self):
|
|
||||||
check_repayment_method(self.repayment_method, self.loan_amount, self.repayment_amount, self.repayment_periods)
|
|
||||||
self.validate_loan_amount()
|
|
||||||
self.get_repayment_details()
|
|
||||||
|
|
||||||
def validate_loan_amount(self):
|
|
||||||
maximum_loan_limit = frappe.db.get_value('Loan Type', self.loan_type, 'maximum_loan_amount')
|
|
||||||
if maximum_loan_limit and self.loan_amount > maximum_loan_limit:
|
|
||||||
frappe.throw(_("Loan Amount cannot exceed Maximum Loan Amount of {0}").format(maximum_loan_limit))
|
|
||||||
|
|
||||||
def get_repayment_details(self):
|
|
||||||
if self.repayment_method == "Repay Over Number of Periods":
|
|
||||||
self.repayment_amount = get_monthly_repayment_amount(self.repayment_method, self.loan_amount, self.rate_of_interest, self.repayment_periods)
|
|
||||||
|
|
||||||
if self.repayment_method == "Repay Fixed Amount per Period":
|
|
||||||
monthly_interest_rate = flt(self.rate_of_interest) / (12 *100)
|
|
||||||
if monthly_interest_rate:
|
|
||||||
monthly_interest_amount = self.loan_amount * monthly_interest_rate
|
|
||||||
if monthly_interest_amount >= self.repayment_amount:
|
|
||||||
frappe.throw(_("Repayment amount {} should be greater than monthly interest amount {}").
|
|
||||||
format(self.repayment_amount, monthly_interest_amount))
|
|
||||||
|
|
||||||
self.repayment_periods = math.ceil((math.log(self.repayment_amount) -
|
|
||||||
math.log(self.repayment_amount - (monthly_interest_amount))) /
|
|
||||||
(math.log(1 + monthly_interest_rate)))
|
|
||||||
else:
|
|
||||||
self.repayment_periods = self.loan_amount / self.repayment_amount
|
|
||||||
|
|
||||||
self.calculate_payable_amount()
|
|
||||||
|
|
||||||
def calculate_payable_amount(self):
|
|
||||||
balance_amount = self.loan_amount
|
|
||||||
self.total_payable_amount = 0
|
|
||||||
self.total_payable_interest = 0
|
|
||||||
|
|
||||||
while(balance_amount > 0):
|
|
||||||
interest_amount = rounded(balance_amount * flt(self.rate_of_interest) / (12*100))
|
|
||||||
balance_amount = rounded(balance_amount + interest_amount - self.repayment_amount)
|
|
||||||
|
|
||||||
self.total_payable_interest += interest_amount
|
|
||||||
|
|
||||||
self.total_payable_amount = self.loan_amount + self.total_payable_interest
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
|
||||||
def make_employee_loan(source_name, target_doc = None):
|
|
||||||
doclist = get_mapped_doc("Employee Loan Application", source_name, {
|
|
||||||
"Employee Loan Application": {
|
|
||||||
"doctype": "Employee Loan",
|
|
||||||
"validation": {
|
|
||||||
"docstatus": ["=", 1]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, target_doc)
|
|
||||||
|
|
||||||
return doclist
|
|
@ -39,31 +39,19 @@ frappe.ui.form.on('Loan', {
|
|||||||
},
|
},
|
||||||
|
|
||||||
refresh: function (frm) {
|
refresh: function (frm) {
|
||||||
if (frm.doc.docstatus == 1 && frm.doc.status == "Sanctioned") {
|
if (frm.doc.docstatus == 1) {
|
||||||
|
if (frm.doc.status == "Sanctioned") {
|
||||||
frm.add_custom_button(__('Create Disbursement Entry'), function() {
|
frm.add_custom_button(__('Create Disbursement Entry'), function() {
|
||||||
frm.trigger("make_jv");
|
frm.trigger("make_jv");
|
||||||
})
|
}).addClass("btn-primary");
|
||||||
}
|
} else if (frm.doc.status == "Disbursed" && frm.doc.repayment_start_date && (frm.doc.applicant_type == 'Member' || frm.doc.repay_from_salary == 0)) {
|
||||||
if (frm.doc.repayment_schedule) {
|
|
||||||
let total_amount_paid = 0;
|
|
||||||
$.each(frm.doc.repayment_schedule || [], function(i, row) {
|
|
||||||
if (row.paid) {
|
|
||||||
total_amount_paid += row.total_payment;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
frm.set_value("total_amount_paid", total_amount_paid);
|
|
||||||
; }
|
|
||||||
if (frm.doc.docstatus == 1 && frm.doc.repayment_start_date && (frm.doc.applicant_type == 'Member' || frm.doc.repay_from_salary == 0)) {
|
|
||||||
frm.add_custom_button(__('Create Repayment Entry'), function() {
|
frm.add_custom_button(__('Create Repayment Entry'), function() {
|
||||||
frm.trigger("make_repayment_entry");
|
frm.trigger("make_repayment_entry");
|
||||||
})
|
}).addClass("btn-primary");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
frm.trigger("toggle_fields");
|
frm.trigger("toggle_fields");
|
||||||
},
|
},
|
||||||
status: function (frm) {
|
|
||||||
frm.toggle_reqd("disbursement_date", frm.doc.status == 'Disbursed')
|
|
||||||
frm.toggle_reqd("repayment_start_date", frm.doc.status == 'Disbursed')
|
|
||||||
},
|
|
||||||
|
|
||||||
make_jv: function (frm) {
|
make_jv: function (frm) {
|
||||||
frappe.call({
|
frappe.call({
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"allow_copy": 0,
|
"allow_copy": 0,
|
||||||
|
"allow_events_in_timeline": 0,
|
||||||
"allow_guest_to_view": 0,
|
"allow_guest_to_view": 0,
|
||||||
"allow_import": 1,
|
"allow_import": 1,
|
||||||
"allow_rename": 0,
|
"allow_rename": 0,
|
||||||
@ -20,6 +21,7 @@
|
|||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
|
"fetch_if_empty": 0,
|
||||||
"fieldname": "applicant_type",
|
"fieldname": "applicant_type",
|
||||||
"fieldtype": "Select",
|
"fieldtype": "Select",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@ -53,6 +55,7 @@
|
|||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
|
"fetch_if_empty": 0,
|
||||||
"fieldname": "applicant",
|
"fieldname": "applicant",
|
||||||
"fieldtype": "Dynamic Link",
|
"fieldtype": "Dynamic Link",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@ -86,6 +89,7 @@
|
|||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
|
"fetch_if_empty": 0,
|
||||||
"fieldname": "applicant_name",
|
"fieldname": "applicant_name",
|
||||||
"fieldtype": "Data",
|
"fieldtype": "Data",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@ -118,6 +122,7 @@
|
|||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
|
"fetch_if_empty": 0,
|
||||||
"fieldname": "loan_application",
|
"fieldname": "loan_application",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@ -151,6 +156,7 @@
|
|||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
|
"fetch_if_empty": 0,
|
||||||
"fieldname": "loan_type",
|
"fieldname": "loan_type",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@ -184,6 +190,7 @@
|
|||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
|
"fetch_if_empty": 0,
|
||||||
"fieldname": "column_break_3",
|
"fieldname": "column_break_3",
|
||||||
"fieldtype": "Column Break",
|
"fieldtype": "Column Break",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@ -215,7 +222,8 @@
|
|||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
"default": "",
|
"default": "Today",
|
||||||
|
"fetch_if_empty": 0,
|
||||||
"fieldname": "posting_date",
|
"fieldname": "posting_date",
|
||||||
"fieldtype": "Date",
|
"fieldtype": "Date",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@ -248,6 +256,7 @@
|
|||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
|
"fetch_if_empty": 0,
|
||||||
"fieldname": "company",
|
"fieldname": "company",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@ -282,6 +291,7 @@
|
|||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
"default": "Sanctioned",
|
"default": "Sanctioned",
|
||||||
|
"fetch_if_empty": 0,
|
||||||
"fieldname": "status",
|
"fieldname": "status",
|
||||||
"fieldtype": "Select",
|
"fieldtype": "Select",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@ -299,7 +309,7 @@
|
|||||||
"precision": "",
|
"precision": "",
|
||||||
"print_hide": 0,
|
"print_hide": 0,
|
||||||
"print_hide_if_no_value": 0,
|
"print_hide_if_no_value": 0,
|
||||||
"read_only": 0,
|
"read_only": 1,
|
||||||
"remember_last_selected_value": 0,
|
"remember_last_selected_value": 0,
|
||||||
"report_hide": 0,
|
"report_hide": 0,
|
||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
@ -316,6 +326,7 @@
|
|||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
"depends_on": "eval:doc.applicant_type==\"Employee\"",
|
"depends_on": "eval:doc.applicant_type==\"Employee\"",
|
||||||
|
"fetch_if_empty": 0,
|
||||||
"fieldname": "repay_from_salary",
|
"fieldname": "repay_from_salary",
|
||||||
"fieldtype": "Check",
|
"fieldtype": "Check",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@ -348,6 +359,7 @@
|
|||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
|
"fetch_if_empty": 0,
|
||||||
"fieldname": "section_break_8",
|
"fieldname": "section_break_8",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@ -380,6 +392,7 @@
|
|||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
|
"fetch_if_empty": 0,
|
||||||
"fieldname": "loan_amount",
|
"fieldname": "loan_amount",
|
||||||
"fieldtype": "Currency",
|
"fieldtype": "Currency",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@ -415,6 +428,7 @@
|
|||||||
"columns": 0,
|
"columns": 0,
|
||||||
"default": "",
|
"default": "",
|
||||||
"fetch_from": "loan_type.rate_of_interest",
|
"fetch_from": "loan_type.rate_of_interest",
|
||||||
|
"fetch_if_empty": 0,
|
||||||
"fieldname": "rate_of_interest",
|
"fieldname": "rate_of_interest",
|
||||||
"fieldtype": "Percent",
|
"fieldtype": "Percent",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@ -448,6 +462,8 @@
|
|||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
|
"depends_on": "eval:doc.status==\"Disbursed\"",
|
||||||
|
"fetch_if_empty": 0,
|
||||||
"fieldname": "disbursement_date",
|
"fieldname": "disbursement_date",
|
||||||
"fieldtype": "Date",
|
"fieldtype": "Date",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@ -480,6 +496,7 @@
|
|||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
|
"fetch_if_empty": 0,
|
||||||
"fieldname": "repayment_start_date",
|
"fieldname": "repayment_start_date",
|
||||||
"fieldtype": "Date",
|
"fieldtype": "Date",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@ -499,7 +516,7 @@
|
|||||||
"read_only": 0,
|
"read_only": 0,
|
||||||
"remember_last_selected_value": 0,
|
"remember_last_selected_value": 0,
|
||||||
"report_hide": 0,
|
"report_hide": 0,
|
||||||
"reqd": 0,
|
"reqd": 1,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
"translatable": 0,
|
"translatable": 0,
|
||||||
@ -512,6 +529,7 @@
|
|||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
|
"fetch_if_empty": 0,
|
||||||
"fieldname": "column_break_11",
|
"fieldname": "column_break_11",
|
||||||
"fieldtype": "Column Break",
|
"fieldtype": "Column Break",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@ -544,6 +562,7 @@
|
|||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
"default": "Repay Over Number of Periods",
|
"default": "Repay Over Number of Periods",
|
||||||
|
"fetch_if_empty": 0,
|
||||||
"fieldname": "repayment_method",
|
"fieldname": "repayment_method",
|
||||||
"fieldtype": "Select",
|
"fieldtype": "Select",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@ -579,6 +598,7 @@
|
|||||||
"columns": 0,
|
"columns": 0,
|
||||||
"default": "",
|
"default": "",
|
||||||
"depends_on": "",
|
"depends_on": "",
|
||||||
|
"fetch_if_empty": 0,
|
||||||
"fieldname": "repayment_periods",
|
"fieldname": "repayment_periods",
|
||||||
"fieldtype": "Int",
|
"fieldtype": "Int",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@ -613,6 +633,7 @@
|
|||||||
"columns": 0,
|
"columns": 0,
|
||||||
"default": "",
|
"default": "",
|
||||||
"depends_on": "",
|
"depends_on": "",
|
||||||
|
"fetch_if_empty": 0,
|
||||||
"fieldname": "monthly_repayment_amount",
|
"fieldname": "monthly_repayment_amount",
|
||||||
"fieldtype": "Currency",
|
"fieldtype": "Currency",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@ -646,6 +667,7 @@
|
|||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 1,
|
"collapsible": 1,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
|
"fetch_if_empty": 0,
|
||||||
"fieldname": "account_info",
|
"fieldname": "account_info",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@ -678,6 +700,7 @@
|
|||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
|
"fetch_if_empty": 0,
|
||||||
"fieldname": "mode_of_payment",
|
"fieldname": "mode_of_payment",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@ -711,6 +734,7 @@
|
|||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
|
"fetch_if_empty": 0,
|
||||||
"fieldname": "payment_account",
|
"fieldname": "payment_account",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@ -744,6 +768,7 @@
|
|||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
|
"fetch_if_empty": 0,
|
||||||
"fieldname": "column_break_9",
|
"fieldname": "column_break_9",
|
||||||
"fieldtype": "Column Break",
|
"fieldtype": "Column Break",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@ -775,6 +800,7 @@
|
|||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
|
"fetch_if_empty": 0,
|
||||||
"fieldname": "loan_account",
|
"fieldname": "loan_account",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@ -808,6 +834,7 @@
|
|||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
|
"fetch_if_empty": 0,
|
||||||
"fieldname": "interest_income_account",
|
"fieldname": "interest_income_account",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@ -841,6 +868,7 @@
|
|||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
|
"fetch_if_empty": 0,
|
||||||
"fieldname": "section_break_15",
|
"fieldname": "section_break_15",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@ -873,6 +901,7 @@
|
|||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
|
"fetch_if_empty": 0,
|
||||||
"fieldname": "repayment_schedule",
|
"fieldname": "repayment_schedule",
|
||||||
"fieldtype": "Table",
|
"fieldtype": "Table",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@ -906,6 +935,7 @@
|
|||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
|
"fetch_if_empty": 0,
|
||||||
"fieldname": "section_break_17",
|
"fieldname": "section_break_17",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@ -939,6 +969,7 @@
|
|||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
"default": "0",
|
"default": "0",
|
||||||
|
"fetch_if_empty": 0,
|
||||||
"fieldname": "total_payment",
|
"fieldname": "total_payment",
|
||||||
"fieldtype": "Currency",
|
"fieldtype": "Currency",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@ -972,6 +1003,7 @@
|
|||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
|
"fetch_if_empty": 0,
|
||||||
"fieldname": "column_break_19",
|
"fieldname": "column_break_19",
|
||||||
"fieldtype": "Column Break",
|
"fieldtype": "Column Break",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@ -1004,6 +1036,7 @@
|
|||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
"default": "0",
|
"default": "0",
|
||||||
|
"fetch_if_empty": 0,
|
||||||
"fieldname": "total_interest_payable",
|
"fieldname": "total_interest_payable",
|
||||||
"fieldtype": "Currency",
|
"fieldtype": "Currency",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@ -1037,6 +1070,7 @@
|
|||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
|
"fetch_if_empty": 0,
|
||||||
"fieldname": "total_amount_paid",
|
"fieldname": "total_amount_paid",
|
||||||
"fieldtype": "Currency",
|
"fieldtype": "Currency",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@ -1070,6 +1104,7 @@
|
|||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
|
"fetch_if_empty": 0,
|
||||||
"fieldname": "amended_from",
|
"fieldname": "amended_from",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@ -1106,7 +1141,7 @@
|
|||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 0,
|
"istable": 0,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"modified": "2018-08-21 16:15:53.267145",
|
"modified": "2019-07-10 13:04:20.953694",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "HR",
|
"module": "HR",
|
||||||
"name": "Loan",
|
"name": "Loan",
|
||||||
@ -1149,7 +1184,6 @@
|
|||||||
"set_user_permissions": 0,
|
"set_user_permissions": 0,
|
||||||
"share": 0,
|
"share": 0,
|
||||||
"submit": 0,
|
"submit": 0,
|
||||||
"user_permission_doctypes": "[\"Employee\"]",
|
|
||||||
"write": 0
|
"write": 0
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
@ -6,30 +6,34 @@ from __future__ import unicode_literals
|
|||||||
import frappe, math, json
|
import frappe, math, json
|
||||||
import erpnext
|
import erpnext
|
||||||
from frappe import _
|
from frappe import _
|
||||||
from frappe.utils import flt, rounded, add_months, nowdate
|
from frappe.utils import flt, rounded, add_months, nowdate, getdate
|
||||||
from erpnext.controllers.accounts_controller import AccountsController
|
from erpnext.controllers.accounts_controller import AccountsController
|
||||||
|
|
||||||
class Loan(AccountsController):
|
class Loan(AccountsController):
|
||||||
def validate(self):
|
def validate(self):
|
||||||
check_repayment_method(self.repayment_method, self.loan_amount, self.monthly_repayment_amount, self.repayment_periods)
|
validate_repayment_method(self.repayment_method, self.loan_amount, self.monthly_repayment_amount, self.repayment_periods)
|
||||||
if not self.company:
|
self.set_missing_fields()
|
||||||
self.company = erpnext.get_default_company()
|
|
||||||
if not self.posting_date:
|
|
||||||
self.posting_date = nowdate()
|
|
||||||
if self.loan_type and not self.rate_of_interest:
|
|
||||||
self.rate_of_interest = frappe.db.get_value("Loan Type", self.loan_type, "rate_of_interest")
|
|
||||||
if self.repayment_method == "Repay Over Number of Periods":
|
|
||||||
self.monthly_repayment_amount = get_monthly_repayment_amount(self.repayment_method, self.loan_amount, self.rate_of_interest, self.repayment_periods)
|
|
||||||
if self.status == "Repaid/Closed":
|
|
||||||
self.total_amount_paid = self.total_payment
|
|
||||||
if self.status == 'Disbursed' and self.repayment_start_date < self.disbursement_date:
|
|
||||||
frappe.throw(_("Repayment Start Date cannot be before Disbursement Date."))
|
|
||||||
|
|
||||||
if self.status == "Disbursed":
|
|
||||||
self.make_repayment_schedule()
|
self.make_repayment_schedule()
|
||||||
self.set_repayment_period()
|
self.set_repayment_period()
|
||||||
self.calculate_totals()
|
self.calculate_totals()
|
||||||
|
|
||||||
|
def set_missing_fields(self):
|
||||||
|
if not self.company:
|
||||||
|
self.company = erpnext.get_default_company()
|
||||||
|
|
||||||
|
if not self.posting_date:
|
||||||
|
self.posting_date = nowdate()
|
||||||
|
|
||||||
|
if self.loan_type and not self.rate_of_interest:
|
||||||
|
self.rate_of_interest = frappe.db.get_value("Loan Type", self.loan_type, "rate_of_interest")
|
||||||
|
|
||||||
|
if self.repayment_method == "Repay Over Number of Periods":
|
||||||
|
self.monthly_repayment_amount = get_monthly_repayment_amount(self.repayment_method, self.loan_amount, self.rate_of_interest, self.repayment_periods)
|
||||||
|
|
||||||
|
if self.status == "Repaid/Closed":
|
||||||
|
self.total_amount_paid = self.total_payment
|
||||||
|
|
||||||
|
|
||||||
def make_jv_entry(self):
|
def make_jv_entry(self):
|
||||||
self.check_permission('write')
|
self.check_permission('write')
|
||||||
journal_entry = frappe.new_doc('Journal Entry')
|
journal_entry = frappe.new_doc('Journal Entry')
|
||||||
@ -105,20 +109,31 @@ def update_total_amount_paid(doc):
|
|||||||
frappe.db.set_value("Loan", doc.name, "total_amount_paid", total_amount_paid)
|
frappe.db.set_value("Loan", doc.name, "total_amount_paid", total_amount_paid)
|
||||||
|
|
||||||
def update_disbursement_status(doc):
|
def update_disbursement_status(doc):
|
||||||
disbursement = frappe.db.sql("""select posting_date, ifnull(sum(credit_in_account_currency), 0) as disbursed_amount
|
disbursement = frappe.db.sql("""
|
||||||
from `tabGL Entry` where account = %s and against_voucher_type = 'Loan' and against_voucher = %s""",
|
select posting_date, ifnull(sum(credit_in_account_currency), 0) as disbursed_amount
|
||||||
(doc.payment_account, doc.name), as_dict=1)[0]
|
from `tabGL Entry`
|
||||||
if disbursement.disbursed_amount == doc.loan_amount:
|
where account = %s and against_voucher_type = 'Loan' and against_voucher = %s
|
||||||
frappe.db.set_value("Loan", doc.name , "status", "Disbursed")
|
""", (doc.payment_account, doc.name), as_dict=1)[0]
|
||||||
if disbursement.disbursed_amount == 0:
|
|
||||||
frappe.db.set_value("Loan", doc.name , "status", "Sanctioned")
|
|
||||||
if disbursement.disbursed_amount > doc.loan_amount:
|
|
||||||
frappe.throw(_("Disbursed Amount cannot be greater than Loan Amount {0}").format(doc.loan_amount))
|
|
||||||
if disbursement.disbursed_amount > 0:
|
|
||||||
frappe.db.set_value("Loan", doc.name , "disbursement_date", disbursement.posting_date)
|
|
||||||
frappe.db.set_value("Loan", doc.name , "repayment_start_date", disbursement.posting_date)
|
|
||||||
|
|
||||||
def check_repayment_method(repayment_method, loan_amount, monthly_repayment_amount, repayment_periods):
|
disbursement_date = None
|
||||||
|
if not disbursement or disbursement.disbursed_amount == 0:
|
||||||
|
status = "Sanctioned"
|
||||||
|
elif disbursement.disbursed_amount == doc.loan_amount:
|
||||||
|
disbursement_date = disbursement.posting_date
|
||||||
|
status = "Disbursed"
|
||||||
|
elif disbursement.disbursed_amount > doc.loan_amount:
|
||||||
|
frappe.throw(_("Disbursed Amount cannot be greater than Loan Amount {0}").format(doc.loan_amount))
|
||||||
|
|
||||||
|
if status == 'Disbursed' and getdate(disbursement_date) > getdate(frappe.db.get_value("Loan", doc.name, "repayment_start_date")):
|
||||||
|
frappe.throw(_("Disbursement Date cannot be after Loan Repayment Start Date"))
|
||||||
|
|
||||||
|
frappe.db.sql("""
|
||||||
|
update `tabLoan`
|
||||||
|
set status = %s, disbursement_date = %s
|
||||||
|
where name = %s
|
||||||
|
""", (status, disbursement_date, doc.name))
|
||||||
|
|
||||||
|
def validate_repayment_method(repayment_method, loan_amount, monthly_repayment_amount, repayment_periods):
|
||||||
if repayment_method == "Repay Over Number of Periods" and not repayment_periods:
|
if repayment_method == "Repay Over Number of Periods" and not repayment_periods:
|
||||||
frappe.throw(_("Please enter Repayment Periods"))
|
frappe.throw(_("Please enter Repayment Periods"))
|
||||||
|
|
||||||
|
@ -23,9 +23,8 @@ frappe.ui.form.on('Loan Application', {
|
|||||||
},
|
},
|
||||||
add_toolbar_buttons: function(frm) {
|
add_toolbar_buttons: function(frm) {
|
||||||
if (frm.doc.status == "Approved") {
|
if (frm.doc.status == "Approved") {
|
||||||
frm.add_custom_button(__('Loan'), function() {
|
frm.add_custom_button(__('Create Loan'), function() {
|
||||||
frappe.call({
|
frappe.call({
|
||||||
type: "GET",
|
|
||||||
method: "erpnext.hr.doctype.loan_application.loan_application.make_loan",
|
method: "erpnext.hr.doctype.loan_application.loan_application.make_loan",
|
||||||
args: {
|
args: {
|
||||||
"source_name": frm.doc.name
|
"source_name": frm.doc.name
|
||||||
@ -37,7 +36,7 @@ frappe.ui.form.on('Loan Application', {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
})
|
}).addClass("btn-primary");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -9,11 +9,11 @@ from frappe.utils import flt, rounded
|
|||||||
from frappe.model.mapper import get_mapped_doc
|
from frappe.model.mapper import get_mapped_doc
|
||||||
from frappe.model.document import Document
|
from frappe.model.document import Document
|
||||||
|
|
||||||
from erpnext.hr.doctype.loan.loan import get_monthly_repayment_amount, check_repayment_method
|
from erpnext.hr.doctype.loan.loan import get_monthly_repayment_amount, validate_repayment_method
|
||||||
|
|
||||||
class LoanApplication(Document):
|
class LoanApplication(Document):
|
||||||
def validate(self):
|
def validate(self):
|
||||||
check_repayment_method(self.repayment_method, self.loan_amount, self.repayment_amount, self.repayment_periods)
|
validate_repayment_method(self.repayment_method, self.loan_amount, self.repayment_amount, self.repayment_periods)
|
||||||
self.validate_loan_amount()
|
self.validate_loan_amount()
|
||||||
self.get_repayment_details()
|
self.get_repayment_details()
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user