Merge pull request #29865 from deepeshgarg007/loan_bank_reco
feat: Bank Reconciliation for loan documents
This commit is contained in:
commit
bd80e04aa7
@ -7,6 +7,7 @@ import json
|
||||
import frappe
|
||||
from frappe import _
|
||||
from frappe.model.document import Document
|
||||
from frappe.query_builder.custom import ConstantColumn
|
||||
from frappe.utils import flt
|
||||
|
||||
from erpnext import get_company_currency
|
||||
@ -275,6 +276,10 @@ def check_matching(bank_account, company, transaction, document_types):
|
||||
}
|
||||
|
||||
matching_vouchers = []
|
||||
|
||||
matching_vouchers.extend(get_loan_vouchers(bank_account, transaction,
|
||||
document_types, filters))
|
||||
|
||||
for query in subquery:
|
||||
matching_vouchers.extend(
|
||||
frappe.db.sql(query, filters,)
|
||||
@ -311,6 +316,114 @@ def get_queries(bank_account, company, transaction, document_types):
|
||||
|
||||
return queries
|
||||
|
||||
def get_loan_vouchers(bank_account, transaction, document_types, filters):
|
||||
vouchers = []
|
||||
amount_condition = True if "exact_match" in document_types else False
|
||||
|
||||
if transaction.withdrawal > 0 and "loan_disbursement" in document_types:
|
||||
vouchers.extend(get_ld_matching_query(bank_account, amount_condition, filters))
|
||||
|
||||
if transaction.deposit > 0 and "loan_repayment" in document_types:
|
||||
vouchers.extend(get_lr_matching_query(bank_account, amount_condition, filters))
|
||||
|
||||
return vouchers
|
||||
|
||||
def get_ld_matching_query(bank_account, amount_condition, filters):
|
||||
loan_disbursement = frappe.qb.DocType("Loan Disbursement")
|
||||
matching_reference = loan_disbursement.reference_number == filters.get("reference_number")
|
||||
matching_party = loan_disbursement.applicant_type == filters.get("party_type") and \
|
||||
loan_disbursement.applicant == filters.get("party")
|
||||
|
||||
rank = (
|
||||
frappe.qb.terms.Case()
|
||||
.when(matching_reference, 1)
|
||||
.else_(0)
|
||||
)
|
||||
|
||||
rank1 = (
|
||||
frappe.qb.terms.Case()
|
||||
.when(matching_party, 1)
|
||||
.else_(0)
|
||||
)
|
||||
|
||||
query = frappe.qb.from_(loan_disbursement).select(
|
||||
rank + rank1 + 1,
|
||||
ConstantColumn("Loan Disbursement").as_("doctype"),
|
||||
loan_disbursement.name,
|
||||
loan_disbursement.disbursed_amount,
|
||||
loan_disbursement.reference_number,
|
||||
loan_disbursement.reference_date,
|
||||
loan_disbursement.applicant_type,
|
||||
loan_disbursement.disbursement_date
|
||||
).where(
|
||||
loan_disbursement.docstatus == 1
|
||||
).where(
|
||||
loan_disbursement.clearance_date.isnull()
|
||||
).where(
|
||||
loan_disbursement.disbursement_account == bank_account
|
||||
)
|
||||
|
||||
if amount_condition:
|
||||
query.where(
|
||||
loan_disbursement.disbursed_amount == filters.get('amount')
|
||||
)
|
||||
else:
|
||||
query.where(
|
||||
loan_disbursement.disbursed_amount <= filters.get('amount')
|
||||
)
|
||||
|
||||
vouchers = query.run(as_list=True)
|
||||
|
||||
return vouchers
|
||||
|
||||
def get_lr_matching_query(bank_account, amount_condition, filters):
|
||||
loan_repayment = frappe.qb.DocType("Loan Repayment")
|
||||
matching_reference = loan_repayment.reference_number == filters.get("reference_number")
|
||||
matching_party = loan_repayment.applicant_type == filters.get("party_type") and \
|
||||
loan_repayment.applicant == filters.get("party")
|
||||
|
||||
rank = (
|
||||
frappe.qb.terms.Case()
|
||||
.when(matching_reference, 1)
|
||||
.else_(0)
|
||||
)
|
||||
|
||||
rank1 = (
|
||||
frappe.qb.terms.Case()
|
||||
.when(matching_party, 1)
|
||||
.else_(0)
|
||||
)
|
||||
|
||||
query = frappe.qb.from_(loan_repayment).select(
|
||||
rank + rank1 + 1,
|
||||
ConstantColumn("Loan Repayment").as_("doctype"),
|
||||
loan_repayment.name,
|
||||
loan_repayment.amount_paid,
|
||||
loan_repayment.reference_number,
|
||||
loan_repayment.reference_date,
|
||||
loan_repayment.applicant_type,
|
||||
loan_repayment.posting_date
|
||||
).where(
|
||||
loan_repayment.docstatus == 1
|
||||
).where(
|
||||
loan_repayment.clearance_date.isnull()
|
||||
).where(
|
||||
loan_repayment.payment_account == bank_account
|
||||
)
|
||||
|
||||
if amount_condition:
|
||||
query.where(
|
||||
loan_repayment.amount_paid == filters.get('amount')
|
||||
)
|
||||
else:
|
||||
query.where(
|
||||
loan_repayment.amount_paid <= filters.get('amount')
|
||||
)
|
||||
|
||||
vouchers = query.run()
|
||||
|
||||
return vouchers
|
||||
|
||||
def get_pe_matching_query(amount_condition, account_from_to, transaction):
|
||||
# get matching payment entries query
|
||||
if transaction.deposit > 0:
|
||||
@ -348,7 +461,6 @@ def get_je_matching_query(amount_condition, transaction):
|
||||
# We have mapping at the bank level
|
||||
# So one bank could have both types of bank accounts like asset and liability
|
||||
# So cr_or_dr should be judged only on basis of withdrawal and deposit and not account type
|
||||
company_account = frappe.get_value("Bank Account", transaction.bank_account, "account")
|
||||
cr_or_dr = "credit" if transaction.withdrawal > 0 else "debit"
|
||||
|
||||
return f"""
|
||||
|
@ -49,7 +49,8 @@ class BankTransaction(StatusUpdater):
|
||||
|
||||
def clear_linked_payment_entries(self, for_cancel=False):
|
||||
for payment_entry in self.payment_entries:
|
||||
if payment_entry.payment_document in ["Payment Entry", "Journal Entry", "Purchase Invoice", "Expense Claim"]:
|
||||
if payment_entry.payment_document in ["Payment Entry", "Journal Entry", "Purchase Invoice", "Expense Claim", "Loan Repayment",
|
||||
"Loan Disbursement"]:
|
||||
self.clear_simple_entry(payment_entry, for_cancel=for_cancel)
|
||||
|
||||
elif payment_entry.payment_document == "Sales Invoice":
|
||||
@ -116,11 +117,18 @@ def get_paid_amount(payment_entry, currency, bank_account):
|
||||
payment_entry.payment_entry, paid_amount_field)
|
||||
|
||||
elif payment_entry.payment_document == "Journal Entry":
|
||||
return frappe.db.get_value('Journal Entry Account', {'parent': payment_entry.payment_entry, 'account': bank_account}, "sum(credit_in_account_currency)")
|
||||
return frappe.db.get_value('Journal Entry Account', {'parent': payment_entry.payment_entry, 'account': bank_account},
|
||||
"sum(credit_in_account_currency)")
|
||||
|
||||
elif payment_entry.payment_document == "Expense Claim":
|
||||
return frappe.db.get_value(payment_entry.payment_document, payment_entry.payment_entry, "total_amount_reimbursed")
|
||||
|
||||
elif payment_entry.payment_document == "Loan Disbursement":
|
||||
return frappe.db.get_value(payment_entry.payment_document, payment_entry.payment_entry, "disbursed_amount")
|
||||
|
||||
elif payment_entry.payment_document == "Loan Repayment":
|
||||
return frappe.db.get_value(payment_entry.payment_document, payment_entry.payment_entry, "amount_paid")
|
||||
|
||||
else:
|
||||
frappe.throw("Please reconcile {0}: {1} manually".format(payment_entry.payment_document, payment_entry.payment_entry))
|
||||
|
||||
|
@ -4,7 +4,12 @@
|
||||
|
||||
import frappe
|
||||
from frappe import _
|
||||
from frappe.utils import flt, getdate, nowdate
|
||||
from frappe.query_builder.custom import ConstantColumn
|
||||
from frappe.query_builder.functions import Sum
|
||||
from frappe.utils import flt, getdate
|
||||
from pypika import CustomFunction
|
||||
|
||||
from erpnext.accounts.utils import get_balance_on
|
||||
|
||||
|
||||
def execute(filters=None):
|
||||
@ -18,7 +23,6 @@ def execute(filters=None):
|
||||
|
||||
data = get_entries(filters)
|
||||
|
||||
from erpnext.accounts.utils import get_balance_on
|
||||
balance_as_per_system = get_balance_on(filters["account"], filters["report_date"])
|
||||
|
||||
total_debit, total_credit = 0,0
|
||||
@ -118,7 +122,21 @@ def get_columns():
|
||||
]
|
||||
|
||||
def get_entries(filters):
|
||||
journal_entries = frappe.db.sql("""
|
||||
journal_entries = get_journal_entries(filters)
|
||||
|
||||
payment_entries = get_payment_entries(filters)
|
||||
|
||||
loan_entries = get_loan_entries(filters)
|
||||
|
||||
pos_entries = []
|
||||
if filters.include_pos_transactions:
|
||||
pos_entries = get_pos_entries(filters)
|
||||
|
||||
return sorted(list(payment_entries)+list(journal_entries+list(pos_entries) + list(loan_entries)),
|
||||
key=lambda k: getdate(k['posting_date']))
|
||||
|
||||
def get_journal_entries(filters):
|
||||
return frappe.db.sql("""
|
||||
select "Journal Entry" as payment_document, jv.posting_date,
|
||||
jv.name as payment_entry, jvd.debit_in_account_currency as debit,
|
||||
jvd.credit_in_account_currency as credit, jvd.against_account,
|
||||
@ -130,7 +148,8 @@ def get_entries(filters):
|
||||
and ifnull(jv.clearance_date, '4000-01-01') > %(report_date)s
|
||||
and ifnull(jv.is_opening, 'No') = 'No'""", filters, as_dict=1)
|
||||
|
||||
payment_entries = frappe.db.sql("""
|
||||
def get_payment_entries(filters):
|
||||
return frappe.db.sql("""
|
||||
select
|
||||
"Payment Entry" as payment_document, name as payment_entry,
|
||||
reference_no, reference_date as ref_date,
|
||||
@ -145,9 +164,8 @@ def get_entries(filters):
|
||||
and ifnull(clearance_date, '4000-01-01') > %(report_date)s
|
||||
""", filters, as_dict=1)
|
||||
|
||||
pos_entries = []
|
||||
if filters.include_pos_transactions:
|
||||
pos_entries = frappe.db.sql("""
|
||||
def get_pos_entries(filters):
|
||||
return frappe.db.sql("""
|
||||
select
|
||||
"Sales Invoice Payment" as payment_document, sip.name as payment_entry, sip.amount as debit,
|
||||
si.posting_date, si.debit_to as against_account, sip.clearance_date,
|
||||
@ -161,8 +179,42 @@ def get_entries(filters):
|
||||
si.posting_date ASC, si.name DESC
|
||||
""", filters, as_dict=1)
|
||||
|
||||
return sorted(list(payment_entries)+list(journal_entries+list(pos_entries)),
|
||||
key=lambda k: k['posting_date'] or getdate(nowdate()))
|
||||
def get_loan_entries(filters):
|
||||
loan_docs = []
|
||||
for doctype in ["Loan Disbursement", "Loan Repayment"]:
|
||||
loan_doc = frappe.qb.DocType(doctype)
|
||||
ifnull = CustomFunction('IFNULL', ['value', 'default'])
|
||||
|
||||
if doctype == "Loan Disbursement":
|
||||
amount_field = (loan_doc.disbursed_amount).as_("credit")
|
||||
posting_date = (loan_doc.disbursement_date).as_("posting_date")
|
||||
account = loan_doc.disbursement_account
|
||||
else:
|
||||
amount_field = (loan_doc.amount_paid).as_("debit")
|
||||
posting_date = (loan_doc.posting_date).as_("posting_date")
|
||||
account = loan_doc.payment_account
|
||||
|
||||
entries = frappe.qb.from_(loan_doc).select(
|
||||
ConstantColumn(doctype).as_("payment_document"),
|
||||
(loan_doc.name).as_("payment_entry"),
|
||||
(loan_doc.reference_number).as_("reference_no"),
|
||||
(loan_doc.reference_date).as_("ref_date"),
|
||||
amount_field,
|
||||
posting_date,
|
||||
).where(
|
||||
loan_doc.docstatus == 1
|
||||
).where(
|
||||
account == filters.get('account')
|
||||
).where(
|
||||
posting_date <= getdate(filters.get('report_date'))
|
||||
).where(
|
||||
ifnull(loan_doc.clearance_date, '4000-01-01') > getdate(filters.get('report_date'))
|
||||
).run(as_dict=1)
|
||||
|
||||
loan_docs.extend(entries)
|
||||
|
||||
return loan_docs
|
||||
|
||||
|
||||
def get_amounts_not_reflected_in_system(filters):
|
||||
je_amount = frappe.db.sql("""
|
||||
@ -182,7 +234,40 @@ def get_amounts_not_reflected_in_system(filters):
|
||||
|
||||
pe_amount = flt(pe_amount[0][0]) if pe_amount else 0.0
|
||||
|
||||
return je_amount + pe_amount
|
||||
loan_amount = get_loan_amount(filters)
|
||||
|
||||
return je_amount + pe_amount + loan_amount
|
||||
|
||||
def get_loan_amount(filters):
|
||||
total_amount = 0
|
||||
for doctype in ["Loan Disbursement", "Loan Repayment"]:
|
||||
loan_doc = frappe.qb.DocType(doctype)
|
||||
ifnull = CustomFunction('IFNULL', ['value', 'default'])
|
||||
|
||||
if doctype == "Loan Disbursement":
|
||||
amount_field = Sum(loan_doc.disbursed_amount)
|
||||
posting_date = (loan_doc.disbursement_date).as_("posting_date")
|
||||
account = loan_doc.disbursement_account
|
||||
else:
|
||||
amount_field = Sum(loan_doc.amount_paid)
|
||||
posting_date = (loan_doc.posting_date).as_("posting_date")
|
||||
account = loan_doc.payment_account
|
||||
|
||||
amount = frappe.qb.from_(loan_doc).select(
|
||||
amount_field
|
||||
).where(
|
||||
loan_doc.docstatus == 1
|
||||
).where(
|
||||
account == filters.get('account')
|
||||
).where(
|
||||
posting_date > getdate(filters.get('report_date'))
|
||||
).where(
|
||||
ifnull(loan_doc.clearance_date, '4000-01-01') <= getdate(filters.get('report_date'))
|
||||
).run()[0][0]
|
||||
|
||||
total_amount += flt(amount)
|
||||
|
||||
return amount
|
||||
|
||||
def get_balance_row(label, amount, account_currency):
|
||||
if amount > 0:
|
||||
|
@ -14,11 +14,15 @@
|
||||
"applicant",
|
||||
"section_break_7",
|
||||
"disbursement_date",
|
||||
"clearance_date",
|
||||
"column_break_8",
|
||||
"disbursed_amount",
|
||||
"accounting_dimensions_section",
|
||||
"cost_center",
|
||||
"customer_details_section",
|
||||
"accounting_details",
|
||||
"disbursement_account",
|
||||
"column_break_16",
|
||||
"loan_account",
|
||||
"bank_account",
|
||||
"disbursement_references_section",
|
||||
"reference_date",
|
||||
@ -106,11 +110,6 @@
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Disbursement Details"
|
||||
},
|
||||
{
|
||||
"fieldname": "customer_details_section",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Customer Details"
|
||||
},
|
||||
{
|
||||
"fetch_from": "against_loan.applicant_type",
|
||||
"fieldname": "applicant_type",
|
||||
@ -149,15 +148,48 @@
|
||||
"fieldname": "reference_number",
|
||||
"fieldtype": "Data",
|
||||
"label": "Reference Number"
|
||||
},
|
||||
{
|
||||
"fieldname": "clearance_date",
|
||||
"fieldtype": "Date",
|
||||
"label": "Clearance Date",
|
||||
"no_copy": 1,
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "accounting_details",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Accounting Details"
|
||||
},
|
||||
{
|
||||
"fetch_from": "against_loan.disbursement_account",
|
||||
"fieldname": "disbursement_account",
|
||||
"fieldtype": "Link",
|
||||
"label": "Disbursement Account",
|
||||
"options": "Account",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_16",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"fetch_from": "against_loan.loan_account",
|
||||
"fieldname": "loan_account",
|
||||
"fieldtype": "Link",
|
||||
"label": "Loan Account",
|
||||
"options": "Account",
|
||||
"read_only": 1
|
||||
}
|
||||
],
|
||||
"index_web_pages_for_search": 1,
|
||||
"is_submittable": 1,
|
||||
"links": [],
|
||||
"modified": "2021-04-19 18:09:32.175355",
|
||||
"modified": "2022-02-17 18:23:44.157598",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Loan Management",
|
||||
"name": "Loan Disbursement",
|
||||
"naming_rule": "Expression (old style)",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
@ -194,5 +226,6 @@
|
||||
"quick_entry": 1,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"states": [],
|
||||
"track_changes": 1
|
||||
}
|
@ -42,9 +42,6 @@ class LoanDisbursement(AccountsController):
|
||||
if not self.posting_date:
|
||||
self.posting_date = self.disbursement_date or nowdate()
|
||||
|
||||
if not self.bank_account and self.applicant_type == "Customer":
|
||||
self.bank_account = frappe.db.get_value("Customer", self.applicant, "default_bank_account")
|
||||
|
||||
def validate_disbursal_amount(self):
|
||||
possible_disbursal_amount = get_disbursal_amount(self.against_loan)
|
||||
|
||||
@ -117,12 +114,11 @@ class LoanDisbursement(AccountsController):
|
||||
|
||||
def make_gl_entries(self, cancel=0, adv_adj=0):
|
||||
gle_map = []
|
||||
loan_details = frappe.get_doc("Loan", self.against_loan)
|
||||
|
||||
gle_map.append(
|
||||
self.get_gl_dict({
|
||||
"account": loan_details.loan_account,
|
||||
"against": loan_details.disbursement_account,
|
||||
"account": self.loan_account,
|
||||
"against": self.disbursement_account,
|
||||
"debit": self.disbursed_amount,
|
||||
"debit_in_account_currency": self.disbursed_amount,
|
||||
"against_voucher_type": "Loan",
|
||||
@ -137,8 +133,8 @@ class LoanDisbursement(AccountsController):
|
||||
|
||||
gle_map.append(
|
||||
self.get_gl_dict({
|
||||
"account": loan_details.disbursement_account,
|
||||
"against": loan_details.loan_account,
|
||||
"account": self.disbursement_account,
|
||||
"against": self.loan_account,
|
||||
"credit": self.disbursed_amount,
|
||||
"credit_in_account_currency": self.disbursed_amount,
|
||||
"against_voucher_type": "Loan",
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"actions": [],
|
||||
"autoname": "LM-REP-.####",
|
||||
"creation": "2019-09-03 14:44:39.977266",
|
||||
"creation": "2022-01-25 10:30:02.767941",
|
||||
"doctype": "DocType",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
@ -13,6 +13,7 @@
|
||||
"column_break_3",
|
||||
"company",
|
||||
"posting_date",
|
||||
"clearance_date",
|
||||
"rate_of_interest",
|
||||
"payroll_payable_account",
|
||||
"is_term_loan",
|
||||
@ -37,7 +38,12 @@
|
||||
"total_penalty_paid",
|
||||
"total_interest_paid",
|
||||
"repayment_details",
|
||||
"amended_from"
|
||||
"amended_from",
|
||||
"accounting_details_section",
|
||||
"payment_account",
|
||||
"penalty_income_account",
|
||||
"column_break_36",
|
||||
"loan_account"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
@ -260,12 +266,52 @@
|
||||
"fieldname": "repay_from_salary",
|
||||
"fieldtype": "Check",
|
||||
"label": "Repay From Salary"
|
||||
},
|
||||
{
|
||||
"fieldname": "clearance_date",
|
||||
"fieldtype": "Date",
|
||||
"label": "Clearance Date",
|
||||
"no_copy": 1,
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "accounting_details_section",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Accounting Details"
|
||||
},
|
||||
{
|
||||
"fetch_from": "against_loan.payment_account",
|
||||
"fieldname": "payment_account",
|
||||
"fieldtype": "Link",
|
||||
"label": "Repayment Account",
|
||||
"options": "Account",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_36",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"fetch_from": "against_loan.loan_account",
|
||||
"fieldname": "loan_account",
|
||||
"fieldtype": "Link",
|
||||
"label": "Loan Account",
|
||||
"options": "Account",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fetch_from": "against_loan.penalty_income_account",
|
||||
"fieldname": "penalty_income_account",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 1,
|
||||
"label": "Penalty Income Account",
|
||||
"options": "Account"
|
||||
}
|
||||
],
|
||||
"index_web_pages_for_search": 1,
|
||||
"is_submittable": 1,
|
||||
"links": [],
|
||||
"modified": "2022-01-06 01:51:06.707782",
|
||||
"modified": "2022-02-18 19:10:07.742298",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Loan Management",
|
||||
"name": "Loan Repayment",
|
||||
|
@ -310,7 +310,6 @@ class LoanRepayment(AccountsController):
|
||||
|
||||
def make_gl_entries(self, cancel=0, adv_adj=0):
|
||||
gle_map = []
|
||||
loan_details = frappe.get_doc("Loan", self.against_loan)
|
||||
|
||||
if self.shortfall_amount and self.amount_paid > self.shortfall_amount:
|
||||
remarks = _("Shortfall Repayment of {0}.\nRepayment against Loan: {1}").format(self.shortfall_amount,
|
||||
@ -323,13 +322,13 @@ class LoanRepayment(AccountsController):
|
||||
if self.repay_from_salary:
|
||||
payment_account = self.payroll_payable_account
|
||||
else:
|
||||
payment_account = loan_details.payment_account
|
||||
payment_account = self.payment_account
|
||||
|
||||
if self.total_penalty_paid:
|
||||
gle_map.append(
|
||||
self.get_gl_dict({
|
||||
"account": loan_details.loan_account,
|
||||
"against": loan_details.payment_account,
|
||||
"account": self.loan_account,
|
||||
"against": payment_account,
|
||||
"debit": self.total_penalty_paid,
|
||||
"debit_in_account_currency": self.total_penalty_paid,
|
||||
"against_voucher_type": "Loan",
|
||||
@ -344,8 +343,8 @@ class LoanRepayment(AccountsController):
|
||||
|
||||
gle_map.append(
|
||||
self.get_gl_dict({
|
||||
"account": loan_details.penalty_income_account,
|
||||
"against": loan_details.loan_account,
|
||||
"account": self.penalty_income_account,
|
||||
"against": self.loan_account,
|
||||
"credit": self.total_penalty_paid,
|
||||
"credit_in_account_currency": self.total_penalty_paid,
|
||||
"against_voucher_type": "Loan",
|
||||
@ -359,8 +358,7 @@ class LoanRepayment(AccountsController):
|
||||
gle_map.append(
|
||||
self.get_gl_dict({
|
||||
"account": payment_account,
|
||||
"against": loan_details.loan_account + ", " + loan_details.interest_income_account
|
||||
+ ", " + loan_details.penalty_income_account,
|
||||
"against": self.loan_account + ", " + self.penalty_income_account,
|
||||
"debit": self.amount_paid,
|
||||
"debit_in_account_currency": self.amount_paid,
|
||||
"against_voucher_type": "Loan",
|
||||
@ -368,16 +366,16 @@ class LoanRepayment(AccountsController):
|
||||
"remarks": remarks,
|
||||
"cost_center": self.cost_center,
|
||||
"posting_date": getdate(self.posting_date),
|
||||
"party_type": loan_details.applicant_type if self.repay_from_salary else '',
|
||||
"party": loan_details.applicant if self.repay_from_salary else ''
|
||||
"party_type": self.applicant_type if self.repay_from_salary else '',
|
||||
"party": self.applicant if self.repay_from_salary else ''
|
||||
})
|
||||
)
|
||||
|
||||
gle_map.append(
|
||||
self.get_gl_dict({
|
||||
"account": loan_details.loan_account,
|
||||
"party_type": loan_details.applicant_type,
|
||||
"party": loan_details.applicant,
|
||||
"account": self.loan_account,
|
||||
"party_type": self.applicant_type,
|
||||
"party": self.applicant,
|
||||
"against": payment_account,
|
||||
"credit": self.amount_paid,
|
||||
"credit_in_account_currency": self.amount_paid,
|
||||
|
@ -353,4 +353,5 @@ erpnext.patches.v13_0.update_reserved_qty_closed_wo
|
||||
erpnext.patches.v13_0.update_exchange_rate_settings
|
||||
erpnext.patches.v14_0.delete_amazon_mws_doctype
|
||||
erpnext.patches.v13_0.set_work_order_qty_in_so_from_mr
|
||||
erpnext.patches.v13_0.update_accounts_in_loan_docs
|
||||
erpnext.patches.v14_0.update_batch_valuation_flag
|
||||
|
37
erpnext/patches/v13_0/update_accounts_in_loan_docs.py
Normal file
37
erpnext/patches/v13_0/update_accounts_in_loan_docs.py
Normal file
@ -0,0 +1,37 @@
|
||||
import frappe
|
||||
|
||||
|
||||
def execute():
|
||||
ld = frappe.qb.DocType("Loan Disbursement").as_("ld")
|
||||
lr = frappe.qb.DocType("Loan Repayment").as_("lr")
|
||||
loan = frappe.qb.DocType("Loan")
|
||||
|
||||
frappe.qb.update(
|
||||
ld
|
||||
).inner_join(
|
||||
loan
|
||||
).on(
|
||||
loan.name == ld.against_loan
|
||||
).set(
|
||||
ld.disbursement_account, loan.disbursement_account
|
||||
).set(
|
||||
ld.loan_account, loan.loan_account
|
||||
).where(
|
||||
ld.docstatus < 2
|
||||
).run()
|
||||
|
||||
frappe.qb.update(
|
||||
lr
|
||||
).inner_join(
|
||||
loan
|
||||
).on(
|
||||
loan.name == lr.against_loan
|
||||
).set(
|
||||
lr.payment_account, loan.payment_account
|
||||
).set(
|
||||
lr.loan_account, loan.loan_account
|
||||
).set(
|
||||
lr.penalty_income_account, loan.penalty_income_account
|
||||
).where(
|
||||
lr.docstatus < 2
|
||||
).run()
|
@ -181,6 +181,12 @@ erpnext.accounts.bank_reconciliation.DialogManager = class DialogManager {
|
||||
fieldname: "journal_entry",
|
||||
onchange: () => this.update_options(),
|
||||
},
|
||||
{
|
||||
fieldtype: "Check",
|
||||
label: "Loan Repayment",
|
||||
fieldname: "loan_repayment",
|
||||
onchange: () => this.update_options(),
|
||||
},
|
||||
{
|
||||
fieldname: "column_break_5",
|
||||
fieldtype: "Column Break",
|
||||
@ -191,13 +197,18 @@ erpnext.accounts.bank_reconciliation.DialogManager = class DialogManager {
|
||||
fieldname: "sales_invoice",
|
||||
onchange: () => this.update_options(),
|
||||
},
|
||||
|
||||
{
|
||||
fieldtype: "Check",
|
||||
label: "Purchase Invoice",
|
||||
fieldname: "purchase_invoice",
|
||||
onchange: () => this.update_options(),
|
||||
},
|
||||
{
|
||||
fieldtype: "Check",
|
||||
label: "Show Only Exact Amount",
|
||||
fieldname: "exact_match",
|
||||
onchange: () => this.update_options(),
|
||||
},
|
||||
{
|
||||
fieldname: "column_break_5",
|
||||
fieldtype: "Column Break",
|
||||
@ -210,8 +221,8 @@ erpnext.accounts.bank_reconciliation.DialogManager = class DialogManager {
|
||||
},
|
||||
{
|
||||
fieldtype: "Check",
|
||||
label: "Show Only Exact Amount",
|
||||
fieldname: "exact_match",
|
||||
label: "Loan Disbursement",
|
||||
fieldname: "loan_disbursement",
|
||||
onchange: () => this.update_options(),
|
||||
},
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user