mirror of
https://github.com/frappe/erpnext.git
synced 2026-05-22 06:29:20 +00:00
fix(refactor): loan in HRMS (#20023)
* fix: update laon on salary slip submission and Cancelation * fix(refactor): Loan in HRMS * fix: Changes requested * Update loan.py Co-authored-by: Nabin Hait <nabinhait@gmail.com>
This commit is contained in:
committed by
Nabin Hait
parent
25fd2743a8
commit
fd68a682ca
@@ -9,7 +9,6 @@ from erpnext.controllers.accounts_controller import AccountsController
|
|||||||
from erpnext.accounts.utils import get_balance_on, get_account_currency
|
from erpnext.accounts.utils import get_balance_on, get_account_currency
|
||||||
from erpnext.accounts.party import get_party_account
|
from erpnext.accounts.party import get_party_account
|
||||||
from erpnext.hr.doctype.expense_claim.expense_claim import update_reimbursed_amount
|
from erpnext.hr.doctype.expense_claim.expense_claim import update_reimbursed_amount
|
||||||
from erpnext.hr.doctype.loan.loan import update_disbursement_status, update_total_amount_paid
|
|
||||||
from erpnext.accounts.doctype.invoice_discounting.invoice_discounting import get_party_account_based_on_invoice_discounting
|
from erpnext.accounts.doctype.invoice_discounting.invoice_discounting import get_party_account_based_on_invoice_discounting
|
||||||
|
|
||||||
from six import string_types, iteritems
|
from six import string_types, iteritems
|
||||||
@@ -606,8 +605,8 @@ class JournalEntry(AccountsController):
|
|||||||
for d in self.accounts:
|
for d in self.accounts:
|
||||||
if d.reference_type=="Loan" and flt(d.debit) > 0:
|
if d.reference_type=="Loan" and flt(d.debit) > 0:
|
||||||
doc = frappe.get_doc("Loan", d.reference_name)
|
doc = frappe.get_doc("Loan", d.reference_name)
|
||||||
update_disbursement_status(doc)
|
doc.update_total_amount_paid()
|
||||||
update_total_amount_paid(doc)
|
doc.set_status()
|
||||||
|
|
||||||
def validate_expense_claim(self):
|
def validate_expense_claim(self):
|
||||||
for d in self.accounts:
|
for d in self.accounts:
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -16,6 +16,7 @@ class Loan(AccountsController):
|
|||||||
self.make_repayment_schedule()
|
self.make_repayment_schedule()
|
||||||
self.set_repayment_period()
|
self.set_repayment_period()
|
||||||
self.calculate_totals()
|
self.calculate_totals()
|
||||||
|
self.set_status(from_validate=True)
|
||||||
|
|
||||||
def set_missing_fields(self):
|
def set_missing_fields(self):
|
||||||
if not self.company:
|
if not self.company:
|
||||||
@@ -95,43 +96,57 @@ class Loan(AccountsController):
|
|||||||
self.total_payment = 0
|
self.total_payment = 0
|
||||||
self.total_interest_payable = 0
|
self.total_interest_payable = 0
|
||||||
self.total_amount_paid = 0
|
self.total_amount_paid = 0
|
||||||
for data in self.repayment_schedule:
|
for schedule in self.repayment_schedule:
|
||||||
self.total_payment += data.total_payment
|
self.total_payment += schedule.total_payment
|
||||||
self.total_interest_payable +=data.interest_amount
|
self.total_interest_payable +=schedule.interest_amount
|
||||||
if data.paid:
|
if schedule.paid:
|
||||||
self.total_amount_paid += data.total_payment
|
self.total_amount_paid += schedule.total_payment
|
||||||
|
|
||||||
def update_total_amount_paid(doc):
|
def update_total_amount_paid(self):
|
||||||
total_amount_paid = 0
|
total_amount_paid = 0
|
||||||
for data in doc.repayment_schedule:
|
for schedule in self.repayment_schedule:
|
||||||
if data.paid:
|
if schedule.paid:
|
||||||
total_amount_paid += data.total_payment
|
total_amount_paid += schedule.total_payment
|
||||||
frappe.db.set_value("Loan", doc.name, "total_amount_paid", total_amount_paid)
|
frappe.db.set_value("Loan", self.name, "total_amount_paid", total_amount_paid)
|
||||||
|
|
||||||
def update_disbursement_status(doc):
|
def set_status(self, from_validate=False):
|
||||||
disbursement = frappe.db.sql("""
|
disbursement = self.get_disbursement_entry()
|
||||||
select posting_date, ifnull(sum(credit_in_account_currency), 0) as disbursed_amount
|
disbursement_date = None
|
||||||
from `tabGL Entry`
|
|
||||||
where account = %s and against_voucher_type = 'Loan' and against_voucher = %s
|
|
||||||
""", (doc.payment_account, doc.name), as_dict=1)[0]
|
|
||||||
|
|
||||||
disbursement_date = None
|
self.status = "Draft"
|
||||||
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")):
|
if (not disbursement or disbursement.disbursed_amount == 0) and self.docstatus == 1:
|
||||||
|
self.status = "Sanctioned"
|
||||||
|
if disbursement:
|
||||||
|
self.validate_disbursed_amount_and_loan_amount(disbursement.disbursed_amount)
|
||||||
|
if disbursement.disbursed_amount == self.loan_amount and disbursement.disbursed_amount != 0:
|
||||||
|
self.status = "Disbursed"
|
||||||
|
disbursement_date = disbursement.posting_date
|
||||||
|
self.validate_disbursement_date(disbursement_date, self.status)
|
||||||
|
|
||||||
|
if self.total_amount_paid == self.total_payment:
|
||||||
|
self.status = "Repaid/Closed"
|
||||||
|
|
||||||
|
if not from_validate:
|
||||||
|
frappe.db.set_value("Loan", self.name, "status", self.status)
|
||||||
|
if disbursement_date:
|
||||||
|
frappe.db.set_value("Loan", self.name, "disbursement_date", disbursement_date)
|
||||||
|
|
||||||
|
def validate_disbursement_date(self, disbursement_date, loan_status):
|
||||||
|
if loan_status == 'Disbursed' and getdate(disbursement_date) > getdate(frappe.db.get_value("Loan", self.name, "repayment_start_date")):
|
||||||
frappe.throw(_("Disbursement Date cannot be after Loan Repayment Start Date"))
|
frappe.throw(_("Disbursement Date cannot be after Loan Repayment Start Date"))
|
||||||
|
|
||||||
frappe.db.sql("""
|
|
||||||
update `tabLoan`
|
def validate_disbursed_amount_and_loan_amount(self, disbursed_amount):
|
||||||
set status = %s, disbursement_date = %s
|
if disbursed_amount > self.loan_amount:
|
||||||
where name = %s
|
frappe.throw(_("Disbursed Amount cannot be greater than Loan Amount {0}").format(self.loan_amount))
|
||||||
""", (status, disbursement_date, doc.name))
|
|
||||||
|
def get_disbursement_entry(self):
|
||||||
|
return frappe.db.sql("""
|
||||||
|
select posting_date, ifnull(sum(credit_in_account_currency), 0) as disbursed_amount
|
||||||
|
from `tabGL Entry`
|
||||||
|
where account = %s and against_voucher_type = 'Loan' and against_voucher = %s
|
||||||
|
""", (self.payment_account, self.name), as_dict=1)[0]
|
||||||
|
|
||||||
def validate_repayment_method(repayment_method, loan_amount, monthly_repayment_amount, repayment_periods):
|
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:
|
||||||
|
|||||||
@@ -62,6 +62,7 @@ class SalarySlip(TransactionBase):
|
|||||||
if self.net_pay < 0:
|
if self.net_pay < 0:
|
||||||
frappe.throw(_("Net Pay cannot be less than 0"))
|
frappe.throw(_("Net Pay cannot be less than 0"))
|
||||||
else:
|
else:
|
||||||
|
self.update_loans()
|
||||||
self.set_status()
|
self.set_status()
|
||||||
self.update_status(self.name)
|
self.update_status(self.name)
|
||||||
self.update_salary_slip_in_additional_salary()
|
self.update_salary_slip_in_additional_salary()
|
||||||
@@ -69,6 +70,7 @@ class SalarySlip(TransactionBase):
|
|||||||
self.email_salary_slip()
|
self.email_salary_slip()
|
||||||
|
|
||||||
def on_cancel(self):
|
def on_cancel(self):
|
||||||
|
self.update_loans()
|
||||||
self.set_status()
|
self.set_status()
|
||||||
self.update_status()
|
self.update_status()
|
||||||
self.update_salary_slip_in_additional_salary()
|
self.update_salary_slip_in_additional_salary()
|
||||||
@@ -764,7 +766,8 @@ class SalarySlip(TransactionBase):
|
|||||||
self.total_principal_amount += loan.principal_amount
|
self.total_principal_amount += loan.principal_amount
|
||||||
|
|
||||||
def get_loan_details(self):
|
def get_loan_details(self):
|
||||||
return frappe.db.sql("""select rps.principal_amount, rps.interest_amount, l.name,
|
return frappe.db.sql("""select rps.principal_amount,
|
||||||
|
rps.name as repayment_name, rps.interest_amount, l.name,
|
||||||
rps.total_payment, l.loan_account, l.interest_income_account
|
rps.total_payment, l.loan_account, l.interest_income_account
|
||||||
from
|
from
|
||||||
`tabRepayment Schedule` as rps, `tabLoan` as l
|
`tabRepayment Schedule` as rps, `tabLoan` as l
|
||||||
@@ -815,6 +818,17 @@ class SalarySlip(TransactionBase):
|
|||||||
timesheet.set_status()
|
timesheet.set_status()
|
||||||
timesheet.save()
|
timesheet.save()
|
||||||
|
|
||||||
|
def update_loans(self):
|
||||||
|
for loan in self.get_loan_details():
|
||||||
|
doc = frappe.get_doc("Loan", loan.name)
|
||||||
|
|
||||||
|
#setting repayment schedule and updating total amount to pay
|
||||||
|
repayment_status = 1 if doc.docstatus == 1 else 0
|
||||||
|
frappe.db.set_value("Repayment Schedule", loan.repayment_name, "paid", repayment_status)
|
||||||
|
doc.reload()
|
||||||
|
doc.update_total_amount_paid()
|
||||||
|
doc.set_status()
|
||||||
|
|
||||||
def set_status(self, status=None):
|
def set_status(self, status=None):
|
||||||
'''Get and update status'''
|
'''Get and update status'''
|
||||||
if not status:
|
if not status:
|
||||||
|
|||||||
Reference in New Issue
Block a user