brotherton-erpnext/erpnext/patches/v13_0/update_old_loans.py

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

201 lines
6.3 KiB
Python
Raw Normal View History

2020-05-17 17:56:59 +00:00
import frappe
2020-08-07 10:51:41 +00:00
from frappe import _
2020-11-11 08:27:10 +00:00
from frappe.model.naming import make_autoname
2020-12-31 07:25:35 +00:00
from frappe.utils import flt, nowdate
2020-05-17 17:56:59 +00:00
from erpnext.accounts.doctype.account.test_account import create_account
from erpnext.loan_management.doctype.loan_repayment.loan_repayment import (
get_accrued_interest_entries,
)
2020-05-17 17:56:59 +00:00
from erpnext.loan_management.doctype.process_loan_interest_accrual.process_loan_interest_accrual import (
2020-11-10 16:38:02 +00:00
process_loan_interest_accrual_for_term_loans,
)
2020-05-17 17:56:59 +00:00
def execute():
# Create a penalty account for loan types
frappe.reload_doc("loan_management", "doctype", "loan_type")
frappe.reload_doc("loan_management", "doctype", "loan")
frappe.reload_doc("loan_management", "doctype", "repayment_schedule")
frappe.reload_doc("loan_management", "doctype", "process_loan_interest_accrual")
frappe.reload_doc("loan_management", "doctype", "loan_repayment")
frappe.reload_doc("loan_management", "doctype", "loan_repayment_detail")
frappe.reload_doc("loan_management", "doctype", "loan_interest_accrual")
frappe.reload_doc("accounts", "doctype", "gl_entry")
2020-11-09 11:47:12 +00:00
frappe.reload_doc("accounts", "doctype", "journal_entry_account")
2020-05-17 17:56:59 +00:00
updated_loan_types = []
2020-12-12 14:01:05 +00:00
loans_to_close = []
2020-05-17 17:56:59 +00:00
2020-11-12 13:13:43 +00:00
# Update old loan status as closed
2020-12-12 14:01:05 +00:00
if frappe.db.has_column("Repayment Schedule", "paid"):
loans_list = frappe.db.sql(
"""SELECT distinct parent from `tabRepayment Schedule`
where paid = 0 and docstatus = 1""",
as_dict=1,
)
2020-11-12 13:13:43 +00:00
2020-12-12 14:01:05 +00:00
loans_to_close = [d.parent for d in loans_list]
2020-11-12 13:13:43 +00:00
2020-11-12 13:17:34 +00:00
if loans_to_close:
frappe.db.sql(
"UPDATE `tabLoan` set status = 'Closed' where name not in (%s)"
% (", ".join(["%s"] * len(loans_to_close))),
tuple(loans_to_close),
)
2022-03-28 13:22:46 +00:00
2020-05-17 17:56:59 +00:00
loans = frappe.get_all(
"Loan",
fields=[
"name",
"loan_type",
"company",
"status",
"mode_of_payment",
"applicant_type",
"applicant",
"loan_account",
"payment_account",
"interest_income_account",
],
2020-11-12 08:07:11 +00:00
filters={"docstatus": 1, "status": ("!=", "Closed")},
)
2020-05-17 17:56:59 +00:00
for loan in loans:
# Update details in Loan Types and Loan
loan_type_company = frappe.db.get_value("Loan Type", loan.loan_type, "company")
2020-11-10 16:38:02 +00:00
loan_type = loan.loan_type
2020-05-17 17:56:59 +00:00
2020-08-07 10:51:41 +00:00
group_income_account = frappe.get_value(
"Account",
{
"company": loan.company,
"is_group": 1,
"root_type": "Income",
"account_name": _("Indirect Income"),
2022-03-28 13:22:46 +00:00
},
2020-08-07 10:51:41 +00:00
)
if not group_income_account:
group_income_account = frappe.get_value(
"Account", {"company": loan.company, "is_group": 1, "root_type": "Income"}
)
2020-05-17 17:56:59 +00:00
penalty_account = create_account(
company=loan.company,
account_type="Income Account",
2020-08-07 10:51:41 +00:00
account_name="Penalty Account",
parent_account=group_income_account,
)
2020-05-17 17:56:59 +00:00
# Same loan type used for multiple companies
if loan_type_company and loan_type_company != loan.company:
# get loan type for appropriate company
loan_type_name = frappe.get_value(
"Loan Type",
{
"company": loan.company,
"mode_of_payment": loan.mode_of_payment,
"loan_account": loan.loan_account,
"payment_account": loan.payment_account,
"disbursement_account": loan.payment_account,
"interest_income_account": loan.interest_income_account,
"penalty_income_account": loan.penalty_income_account,
},
"name",
)
if not loan_type_name:
loan_type_name = create_loan_type(loan, loan_type_name, penalty_account)
# update loan type in loan
frappe.db.sql(
"UPDATE `tabLoan` set loan_type = %s where name = %s", (loan_type_name, loan.name)
)
2020-11-10 16:38:02 +00:00
loan_type = loan_type_name
if loan_type_name not in updated_loan_types:
updated_loan_types.append(loan_type_name)
elif not loan_type_company:
2020-05-17 17:56:59 +00:00
loan_type_doc = frappe.get_doc("Loan Type", loan.loan_type)
loan_type_doc.is_term_loan = 1
loan_type_doc.company = loan.company
loan_type_doc.mode_of_payment = loan.mode_of_payment
loan_type_doc.payment_account = loan.payment_account
loan_type_doc.loan_account = loan.loan_account
loan_type_doc.interest_income_account = loan.interest_income_account
loan_type_doc.penalty_income_account = penalty_account
loan_type_doc.submit()
updated_loan_types.append(loan.loan_type)
2020-11-10 16:38:02 +00:00
loan_type = loan.loan_type
2020-05-17 17:56:59 +00:00
2020-11-10 16:38:02 +00:00
if loan_type in updated_loan_types:
2020-05-17 17:56:59 +00:00
if loan.status == "Fully Disbursed":
status = "Disbursed"
elif loan.status == "Repaid/Closed":
status = "Closed"
else:
status = loan.status
frappe.db.set_value(
"Loan",
loan.name,
{"is_term_loan": 1, "penalty_income_account": penalty_account, "status": status},
)
2020-11-10 16:38:02 +00:00
process_loan_interest_accrual_for_term_loans(
posting_date=nowdate(), loan_type=loan_type, loan=loan.name
2022-03-28 13:22:46 +00:00
)
2020-12-05 17:14:45 +00:00
if frappe.db.has_column("Repayment Schedule", "paid"):
total_principal, total_interest = frappe.db.get_value(
"Repayment Schedule",
{"paid": 1, "parent": loan.name},
["sum(principal_amount) as total_principal", "sum(interest_amount) as total_interest"],
)
accrued_entries = get_accrued_interest_entries(loan.name)
for entry in accrued_entries:
interest_paid = 0
principal_paid = 0
2020-12-31 07:25:35 +00:00
if flt(total_interest) > flt(entry.interest_amount):
interest_paid = flt(entry.interest_amount)
2020-12-05 17:14:45 +00:00
else:
2020-12-31 07:25:35 +00:00
interest_paid = flt(total_interest)
2020-12-05 17:14:45 +00:00
2020-12-31 07:25:35 +00:00
if flt(total_principal) > flt(entry.payable_principal_amount):
principal_paid = flt(entry.payable_principal_amount)
2020-12-05 17:14:45 +00:00
else:
2020-12-31 07:25:35 +00:00
principal_paid = flt(total_principal)
2020-12-05 17:14:45 +00:00
frappe.db.sql(
""" UPDATE `tabLoan Interest Accrual`
SET paid_principal_amount = `paid_principal_amount` + %s,
paid_interest_amount = `paid_interest_amount` + %s
WHERE name = %s""",
(principal_paid, interest_paid, entry.name),
)
2020-12-31 07:25:35 +00:00
total_principal = flt(total_principal) - principal_paid
total_interest = flt(total_interest) - interest_paid
2020-05-17 17:56:59 +00:00
2022-03-28 13:22:46 +00:00
def create_loan_type(loan, loan_type_name, penalty_account):
loan_type_doc = frappe.new_doc("Loan Type")
2020-11-11 08:27:10 +00:00
loan_type_doc.loan_name = make_autoname("Loan Type-.####")
loan_type_doc.is_term_loan = 1
loan_type_doc.company = loan.company
loan_type_doc.mode_of_payment = loan.mode_of_payment
loan_type_doc.payment_account = loan.payment_account
loan_type_doc.disbursement_account = loan.payment_account
loan_type_doc.loan_account = loan.loan_account
loan_type_doc.interest_income_account = loan.interest_income_account
loan_type_doc.penalty_income_account = penalty_account
loan_type_doc.submit()
2020-11-11 07:27:16 +00:00
2020-11-11 08:27:10 +00:00
return loan_type_doc.name